diff --git a/HISTORY.md b/HISTORY.md index 1bf323570db5..035c9085a3c7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -24,8 +24,6 @@ ### C API -* Added functions `tiledb_subarray_partitoner_{next, get_current, done}`. -* Added object `tiledb_subarray_partitioner_t` and functions `tiledb_subarray_partitoner_{alloc, free, set_result_budget, set_result_budget_var, get_result_budget, get_result_budget_var}`. * Added functions `tiledb_subarray_{get_est_result_size, get_est_result_size_var}`. * Added object `tiledb_subarray_t` and functions `tiledb_subarray_{alloc, free, get_layout, get_type, get_ndim, get_domain, add_range, get_range_num, get_range}`. * Added function `tiledb_query_get_layout` diff --git a/doc/source/c-api.rst b/doc/source/c-api.rst index c6a7a85e209a..5a12a0af1e6b 100644 --- a/doc/source/c-api.rst +++ b/doc/source/c-api.rst @@ -373,31 +373,6 @@ Subarray .. doxygenfunction:: tiledb_subarray_get_est_result_size_var :project: TileDB-C -SubarrayPartitioner -------------------- -.. doxygenfunction:: tiledb_subarray_partitioner_alloc - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_free - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_set_result_budget - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_set_result_budget_var - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_set_memory_budget - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_get_result_budget - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_get_result_budget_var - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_get_memory_budget - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_next - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_get_current - :project: TileDB-C -.. doxygenfunction:: tiledb_subarray_partitioner_done - :project: TileDB-C - Filter ------ .. doxygenfunction:: tiledb_filter_alloc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 92d22fda9f1d..8db79851e7de 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,6 +40,7 @@ list(APPEND TILEDB_CORE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../tiledb/sm/c_ # Gather the test source files set(TILEDB_TEST_SOURCES src/helpers.h + src/helpers.cc src/unit-backwards_compat.cc src/unit-buffer.cc src/unit-capi-any.cc @@ -69,7 +70,6 @@ set(TILEDB_TEST_SOURCES src/unit-capi-sparse_real_2.cc src/unit-capi-string.cc src/unit-capi-subarray.cc - src/unit-capi-subarray_partitioner.cc src/unit-capi-uri.cc src/unit-capi-version.cc src/unit-capi-vfs.cc @@ -84,6 +84,9 @@ set(TILEDB_TEST_SOURCES src/unit-s3.cc src/unit-s3-no-multipart.cc src/unit-status.cc + src/unit-SubarrayPartitioner-dense.cc + src/unit-SubarrayPartitioner-error.cc + src/unit-SubarrayPartitioner-sparse.cc src/unit-tbb.cc src/unit-threadpool.cc src/unit-uri.cc diff --git a/test/src/helpers.cc b/test/src/helpers.cc new file mode 100644 index 000000000000..dbfa33fc9ed5 --- /dev/null +++ b/test/src/helpers.cc @@ -0,0 +1,521 @@ +/** + * @file helpers.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2017-2019 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file defines some test suite helper functions. + */ + +#include "helpers.h" +#include "catch.hpp" + +template +void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable) { + bool unsplittable = false; + + // Special case for empty partitions + if (partitions.empty()) { + CHECK(partitioner.next(&unsplittable).ok()); + if (last_unsplittable) { + CHECK(unsplittable); + } else { + CHECK(!unsplittable); + CHECK(partitioner.done()); + } + return; + } + + // Non-empty partitions + for (const auto& p : partitions) { + CHECK(!partitioner.done()); + CHECK(!unsplittable); + CHECK(partitioner.next(&unsplittable).ok()); + auto partition = partitioner.current(); + check_subarray(partition, p); + } + + // Check last unsplittable + if (last_unsplittable) { + CHECK(unsplittable); + } else { + CHECK(!unsplittable); + // CHECK(partitioner.next(&unsplittable).ok()); + // CHECK(!unsplittable); + CHECK(partitioner.done()); + } +} + +template +void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges) { + // Check empty subarray + auto subarray_range_num = subarray.range_num(); + if (ranges.empty()) { + CHECK(subarray_range_num == 0); + return; + } + uint64_t range_num = 1; + for (const auto& dim_ranges : ranges) + range_num *= dim_ranges.size() / 2; + CHECK(subarray_range_num == range_num); + + // Check dim num + auto dim_num = subarray.dim_num(); + CHECK(dim_num == ranges.size()); + + // Check ranges + uint64_t dim_range_num = 0; + const T* range; + for (unsigned i = 0; i < dim_num; ++i) { + CHECK(subarray.get_range_num(i, &dim_range_num).ok()); + CHECK(dim_range_num == ranges[i].size() / 2); + for (uint64_t j = 0; j < dim_range_num; ++j) { + subarray.get_range(i, j, (const void**)&range); + CHECK(range[0] == ranges[i][2 * j]); + CHECK(range[1] == ranges[i][2 * j + 1]); + } + } +} + +void close_array(tiledb_ctx_t* ctx, tiledb_array_t* array) { + int rc = tiledb_array_close(ctx, array); + CHECK(rc == TILEDB_OK); +} + +void create_array( + tiledb_ctx_t* ctx, + const std::string& array_name, + tiledb_array_type_t array_type, + const std::vector& dim_names, + const std::vector& dim_types, + const std::vector& dim_domains, + const std::vector& tile_extents, + const std::vector& attr_names, + const std::vector& attr_types, + const std::vector& cell_val_num, + const std::vector>& compressors, + tiledb_layout_t tile_order, + tiledb_layout_t cell_order, + uint64_t capacity) { + // For easy reference + auto dim_num = dim_names.size(); + auto attr_num = attr_names.size(); + + // Sanity checks + assert(dim_types.size() == dim_num); + assert(dim_domains.size() == dim_num); + assert(tile_extents.size() == dim_num); + assert(attr_types.size() == attr_num); + assert(cell_val_num.size() == attr_num); + assert(compressors.size() == attr_num); + + // Create array schema + tiledb_array_schema_t* array_schema; + int rc = tiledb_array_schema_alloc(ctx, array_type, &array_schema); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_array_schema_set_cell_order(ctx, array_schema, cell_order); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_array_schema_set_tile_order(ctx, array_schema, tile_order); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_array_schema_set_capacity(ctx, array_schema, capacity); + REQUIRE(rc == TILEDB_OK); + + // Create dimensions and domain + tiledb_domain_t* domain; + rc = tiledb_domain_alloc(ctx, &domain); + REQUIRE(rc == TILEDB_OK); + for (size_t i = 0; i < dim_num; ++i) { + tiledb_dimension_t* d; + rc = tiledb_dimension_alloc( + ctx, + dim_names[i].c_str(), + dim_types[i], + dim_domains[i], + tile_extents[i], + &d); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_domain_add_dimension(ctx, domain, d); + REQUIRE(rc == TILEDB_OK); + tiledb_dimension_free(&d); + } + + // Set domain to schema + rc = tiledb_array_schema_set_domain(ctx, array_schema, domain); + REQUIRE(rc == TILEDB_OK); + tiledb_domain_free(&domain); + + // Create attributes + for (size_t i = 0; i < attr_num; ++i) { + tiledb_attribute_t* a; + rc = tiledb_attribute_alloc(ctx, attr_names[i].c_str(), attr_types[i], &a); + REQUIRE(rc == TILEDB_OK); + rc = set_attribute_compression_filter( + ctx, a, compressors[i].first, compressors[i].second); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_attribute_set_cell_val_num(ctx, a, cell_val_num[i]); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_array_schema_add_attribute(ctx, array_schema, a); + REQUIRE(rc == TILEDB_OK); + tiledb_attribute_free(&a); + } + + // Check array schema + rc = tiledb_array_schema_check(ctx, array_schema); + REQUIRE(rc == TILEDB_OK); + + // Create array + rc = tiledb_array_create(ctx, array_name.c_str(), array_schema); + REQUIRE(rc == TILEDB_OK); + + // Clean up + tiledb_array_schema_free(&array_schema); +} + +void create_s3_bucket( + const std::string& bucket_name, + bool s3_supported, + tiledb_ctx_t* ctx, + tiledb_vfs_t* vfs) { + if (s3_supported) { + // Create bucket if it does not exist + int is_bucket = 0; + int rc = tiledb_vfs_is_bucket(ctx, vfs, bucket_name.c_str(), &is_bucket); + REQUIRE(rc == TILEDB_OK); + if (!is_bucket) { + rc = tiledb_vfs_create_bucket(ctx, vfs, bucket_name.c_str()); + REQUIRE(rc == TILEDB_OK); + } + } +} + +void create_ctx_and_vfs( + bool s3_supported, tiledb_ctx_t** ctx, tiledb_vfs_t** vfs) { + // Create TileDB context + tiledb_config_t* config = nullptr; + tiledb_error_t* error = nullptr; + REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK); + REQUIRE(error == nullptr); + if (s3_supported) { +#ifndef TILEDB_TESTS_AWS_S3_CONFIG + REQUIRE( + tiledb_config_set( + config, "vfs.s3.endpoint_override", "localhost:9999", &error) == + TILEDB_OK); + REQUIRE( + tiledb_config_set(config, "vfs.s3.scheme", "http", &error) == + TILEDB_OK); + REQUIRE( + tiledb_config_set( + config, "vfs.s3.use_virtual_addressing", "false", &error) == + TILEDB_OK); + REQUIRE(error == nullptr); +#endif + } + REQUIRE(tiledb_ctx_alloc(config, ctx) == TILEDB_OK); + REQUIRE(error == nullptr); + + // Create VFS + *vfs = nullptr; + REQUIRE(tiledb_vfs_alloc(*ctx, config, vfs) == TILEDB_OK); + tiledb_config_free(&config); +} + +void create_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs) { + remove_dir(path, ctx, vfs); + REQUIRE(tiledb_vfs_create_dir(ctx, vfs, path.c_str()) == TILEDB_OK); +} + +template +void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray) { + tiledb::sm::Subarray ret(array, layout); + + auto dim_num = (unsigned)ranges.size(); + for (unsigned i = 0; i < dim_num; ++i) { + auto dim_range_num = ranges[i].size() / 2; + for (size_t j = 0; j < dim_range_num; ++j) { + ret.add_range(i, &ranges[i][2 * j]); + } + } + + *subarray = ret; +} + +void get_supported_fs(bool* s3_supported, bool* hdfs_supported) { + tiledb_ctx_t* ctx = nullptr; + REQUIRE(tiledb_ctx_alloc(nullptr, &ctx) == TILEDB_OK); + + int is_supported = 0; + int rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_S3, &is_supported); + REQUIRE(rc == TILEDB_OK); + *s3_supported = (bool)is_supported; + rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_HDFS, &is_supported); + REQUIRE(rc == TILEDB_OK); + *hdfs_supported = (bool)is_supported; + + tiledb_ctx_free(&ctx); +} + +void open_array( + tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_query_type_t query_type) { + int rc = tiledb_array_open(ctx, array, query_type); + CHECK(rc == TILEDB_OK); +} + +std::string random_bucket_name(const std::string& prefix) { + std::stringstream ss; + ss << prefix << "-" << std::this_thread::get_id() << "-" + << TILEDB_TIMESTAMP_NOW_MS; + return ss.str(); +} + +void remove_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs) { + int is_dir = 0; + REQUIRE(tiledb_vfs_is_dir(ctx, vfs, path.c_str(), &is_dir) == TILEDB_OK); + if (is_dir) + REQUIRE(tiledb_vfs_remove_dir(ctx, vfs, path.c_str()) == TILEDB_OK); +} + +void remove_s3_bucket( + const std::string& bucket_name, + bool s3_supported, + tiledb_ctx_t* ctx, + tiledb_vfs_t* vfs) { + if (s3_supported) { + int is_bucket = 0; + int rc = tiledb_vfs_is_bucket(ctx, vfs, bucket_name.c_str(), &is_bucket); + CHECK(rc == TILEDB_OK); + if (is_bucket) { + rc = tiledb_vfs_remove_bucket(ctx, vfs, bucket_name.c_str()); + CHECK(rc == TILEDB_OK); + } + } +} + +int set_attribute_compression_filter( + tiledb_ctx_t* ctx, + tiledb_attribute_t* attr, + tiledb_filter_type_t compressor, + int32_t level) { + tiledb_filter_t* filter; + int rc = tiledb_filter_alloc(ctx, compressor, &filter); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_filter_set_option(ctx, filter, TILEDB_COMPRESSION_LEVEL, &level); + REQUIRE(rc == TILEDB_OK); + tiledb_filter_list_t* list; + rc = tiledb_filter_list_alloc(ctx, &list); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_filter_list_add_filter(ctx, list, filter); + REQUIRE(rc == TILEDB_OK); + rc = tiledb_attribute_set_filter_list(ctx, attr, list); + REQUIRE(rc == TILEDB_OK); + + tiledb_filter_free(&filter); + tiledb_filter_list_free(&list); + + return TILEDB_OK; +} + +void write_array( + tiledb_ctx_t* ctx, + const std::string& array_name, + tiledb_layout_t layout, + const AttrBuffers& attr_buffers) { + // Open array + tiledb_array_t* array; + int rc = tiledb_array_alloc(ctx, array_name.c_str(), &array); + CHECK(rc == TILEDB_OK); + rc = tiledb_array_open(ctx, array, TILEDB_WRITE); + CHECK(rc == TILEDB_OK); + + // Create query + tiledb_query_t* query; + rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query); + CHECK(rc == TILEDB_OK); + rc = tiledb_query_set_layout(ctx, query, layout); + CHECK(rc == TILEDB_OK); + + // Set buffers + for (const auto& b : attr_buffers) { + if (b.second.var_ == nullptr) { // Fixed-sized + rc = tiledb_query_set_buffer( + ctx, + query, + b.first.c_str(), + b.second.fixed_, + (uint64_t*)&(b.second.fixed_size_)); + CHECK(rc == TILEDB_OK); + } else { // Var-sized + rc = tiledb_query_set_buffer_var( + ctx, + query, + b.first.c_str(), + (uint64_t*)b.second.fixed_, + (uint64_t*)&(b.second.fixed_size_), + b.second.var_, + (uint64_t*)&(b.second.var_size_)); + CHECK(rc == TILEDB_OK); + } + } + + // Submit query + rc = tiledb_query_submit(ctx, query); + CHECK(rc == TILEDB_OK); + + // Finalize query + rc = tiledb_query_finalize(ctx, query); + CHECK(rc == TILEDB_OK); + + // Close array + rc = tiledb_array_close(ctx, array); + CHECK(rc == TILEDB_OK); + + // Clean up + tiledb_array_free(&array); + tiledb_query_free(&query); +} + +// Explicit template instantiations + +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); +template void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); + +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); +template void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); + +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); +template void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); diff --git a/test/src/helpers.h b/test/src/helpers.h index cc74f06b3e5f..b2f7ce2155f9 100644 --- a/test/src/helpers.h +++ b/test/src/helpers.h @@ -27,14 +27,213 @@ * * @section DESCRIPTION * - * This file defines some test suite helper functions. + * This file declares some test suite helper functions. */ #ifndef TILEDB_TEST_HELPERS_H #define TILEDB_TEST_HELPERS_H -#include "catch.hpp" #include "tiledb.h" +#include "tiledb/sm/array/array.h" +#include "tiledb/sm/enums/layout.h" +#include "tiledb/sm/subarray/subarray.h" + +#include +#include +#include + +// For easy reference +typedef std::pair Compressor; +template +using SubarrayRanges = std::vector>; + +/** Helper struct for the buffers of an attribute (fixed- or var-sized). */ +struct AttrBuffer { + /** + * For fixed-sized attributes, it contains the fixed-sized values. + * For var-sized attributes, it contains the offsets. + * var buffer is nullptr. + */ + void* fixed_; + /** Size of fixed buffer. */ + uint64_t fixed_size_; + /** + * For fixed-sized attributes, it is `nullptr`. + * For var-sized attributes, it contains the var-sized values. + */ + void* var_; + /** Size of var buffer. */ + uint64_t var_size_; +}; +/** Map attribute_name -> AttrBuffer */ +typedef std::map AttrBuffers; + +/** + * Checks that the input partitioner produces the input partitions + * (i.e., subarrays). + * + * @tparam T The datatype of the subarray of the partitioner. + * @param partitioner The partitioner. + * @param ranges The ranges to be checked. + * @param last_unsplittable Whether the last partition is unsplittable. + */ +template +void check_partitions( + tiledb::sm::SubarrayPartitioner& partitioner, + const std::vector>& partitions, + bool last_unsplittable); + +/** + * Checks if the input subarray has the input subarray ranges. + * + * @tparam T The subarray domain datatype + * @param subarray The subarray to be checked. + * @param ranges The ranges to be checked (a vector of ranges per dimension). + */ +template +void check_subarray( + tiledb::sm::Subarray& subarray, const SubarrayRanges& ranges); + +/** + * Closes an array. + * + * @param ctx The TileDB context. + * @param array The array to be closed. + */ +void close_array(tiledb_ctx_t* ctx, tiledb_array_t* array); + +/** + * Helper method to create an array. + * + * @param ctx TileDB context. + * @param array_name The array name. + * @param array_type The array type (dense or sparse). + * @param dim_names The names of dimensions. + * @param dim_types The types of dimensions. + * @param dim_domains The domains of dimensions. + * @param tile_extents The tile extents of dimensions. + * @param attr_names The names of attributes. + * @param attr_types The types of attributes. + * @param cell_val_num The number of values per cell of attributes. + * @param compressors The compressors of attributes. + * @param tile_order The tile order. + * @param cell_order The cell order. + * @param capacity The tile capacity. + */ + +void create_array( + tiledb_ctx_t* ctx, + const std::string& array_name, + tiledb_array_type_t array_type, + const std::vector& dim_names, + const std::vector& dim_types, + const std::vector& dim_domains, + const std::vector& tile_extents, + const std::vector& attr_names, + const std::vector& attr_types, + const std::vector& cell_val_num, + const std::vector>& compressors, + tiledb_layout_t tile_order, + tiledb_layout_t cell_order, + uint64_t capacity); + +/** + * Helper method that creates a directory. + * + * @param path The name of the directory to be created. + * @param ctx The TileDB context. + * @param vfs The VFS object that will create the directory. + */ +void create_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs); + +/** + * Helper method that creates an S3 bucket (if it does not already exist). + * + * @param bucket_name The name of the bucket to be created. + * @param s3_supported The bucket will be created only if this is `true`. + * @param ctx The TileDB context. + * @param vfs The VFS object that will create the bucket. + */ +void create_s3_bucket( + const std::string& bucket_name, + bool s3_supported, + tiledb_ctx_t* ctx, + tiledb_vfs_t* vfs); + +/** + * Creates a subarray for the input array. + * + * @tparam T The datatype of the subarray domain. + * @param array The input array. + * @param ranges The ranges of the subarray to be created. + * @param layout The layout of the subarray. + * @param subarray The subarray to be set. + */ +template +void create_subarray( + tiledb::sm::Array* array, + const SubarrayRanges& ranges, + tiledb::sm::Layout layout, + tiledb::sm::Subarray* subarray); + +/** + * Helper method that creates a TileDB context and a VFS object. + * + * @param s3_supported Indicates whether S3 is supported or not. + * @param ctx The TileDB context to be created. + * @param vfs The VFS object to be created. + */ +void create_ctx_and_vfs( + bool s3_supported, tiledb_ctx_t** ctx, tiledb_vfs_t** vfs); + +/** + * Helper function to get the supported filesystems. + * + * @param s3_supported Set to `true` if S3 is supported. + * @param hdfs_supported Set to `false` if HDFS is supported. + */ +void get_supported_fs(bool* s3_supported, bool* hdfs_supported); + +/** + * Opens an array. + * + * @param ctx The TileDB context. + * @param array The array to be opened. + * @param query_type The query type. + */ +void open_array(tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_query_type_t); + +/** + * Returns a random bucket name, with `prefix` as prefix and using + * the thread id as a "random" suffix. + * + * @param prefix The prefix of the bucket name. + * @return A random bucket name. + */ +std::string random_bucket_name(const std::string& prefix); + +/** + * Helper method that removes a directory. + * + * @param path The name of the directory to be removed. + * @param ctx The TileDB context. + * @param vfs The VFS object that will remove the directory. + */ +void remove_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs); + +/** + * Helper method that removes an S3 bucket. + * + * @param bucket_name The name of the bucket to be removed. + * @param s3_supported The bucket is removed only when this is `true`. + * @param ctx The TileDB context. + * @param vfs The VFS object that will remove the bucket. + */ +void remove_s3_bucket( + const std::string& bucket_name, + bool s3_supported, + tiledb_ctx_t* ctx, + tiledb_vfs_t* vfs); /** * Helper method to configure a single-stage filter list with the given @@ -45,27 +244,24 @@ * @param compressor Compressor type to use * @param level Compression level to use */ -static int set_attribute_compression_filter( +int set_attribute_compression_filter( tiledb_ctx_t* ctx, tiledb_attribute_t* attr, tiledb_filter_type_t compressor, - int32_t level) { - tiledb_filter_t* filter; - int rc = tiledb_filter_alloc(ctx, compressor, &filter); - REQUIRE(rc == TILEDB_OK); - rc = tiledb_filter_set_option(ctx, filter, TILEDB_COMPRESSION_LEVEL, &level); - REQUIRE(rc == TILEDB_OK); - tiledb_filter_list_t* list; - rc = tiledb_filter_list_alloc(ctx, &list); - REQUIRE(rc == TILEDB_OK); - rc = tiledb_filter_list_add_filter(ctx, list, filter); - REQUIRE(rc == TILEDB_OK); - rc = tiledb_attribute_set_filter_list(ctx, attr, list); - - tiledb_filter_free(&filter); - tiledb_filter_list_free(&list); - - return TILEDB_OK; -} + int32_t level); + +/** + * Performs a single write to an array. + * + * @param ctx The TileDB context. + * @param array_name The array name. + * @param layout The layout to write into. + * @param attr_buffers The attribute buffers to be written. + */ +void write_array( + tiledb_ctx_t* ctx, + const std::string& array_name, + tiledb_layout_t layout, + const AttrBuffers& attr_buffers); #endif diff --git a/test/src/unit-SubarrayPartitioner-dense.cc b/test/src/unit-SubarrayPartitioner-dense.cc new file mode 100644 index 000000000000..e43ff2662ebc --- /dev/null +++ b/test/src/unit-SubarrayPartitioner-dense.cc @@ -0,0 +1,2679 @@ +/** + * @file unit-SubarrayPartitioner-dense.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2017-2019 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * Tests the `SubarrayPartitioner` class for dense arrays. + */ + +#include "test/src/helpers.h" +#include "tiledb/sm/c_api/tiledb_struct_def.h" +#include "tiledb/sm/subarray/subarray_partitioner.h" + +#ifdef _WIN32 +#include "tiledb/sm/filesystem/win.h" +#else +#include "tiledb/sm/filesystem/posix.h" +#endif + +#include +#include + +using namespace tiledb::sm; + +/* ********************************* */ +/* STRUCT DEFINITION */ +/* ********************************* */ + +struct SubarrayPartitionerDenseFx { + tiledb_ctx_t* ctx_; + tiledb_vfs_t* vfs_; + bool s3_supported_, hdfs_supported_; + std::string temp_dir_; + const std::string s3_bucket_name_ = + "s3://" + random_bucket_name("tiledb") + "/"; + std::string array_name_; + const char* ARRAY_NAME = "subarray_partitioner_dense"; + tiledb_array_t* array_ = nullptr; + + SubarrayPartitionerDenseFx(); + ~SubarrayPartitionerDenseFx(); +}; + +SubarrayPartitionerDenseFx::SubarrayPartitionerDenseFx() { + ctx_ = nullptr; + vfs_ = nullptr; + hdfs_supported_ = false; + s3_supported_ = false; + + get_supported_fs(&s3_supported_, &hdfs_supported_); + create_ctx_and_vfs(s3_supported_, &ctx_, &vfs_); + create_s3_bucket(s3_bucket_name_, s3_supported_, ctx_, vfs_); + +// Create temporary directory based on the supported filesystem +#ifdef _WIN32 + temp_dir_ = tiledb::sm::Win::current_dir() + "\\tiledb_test\\"; +#else + temp_dir_ = "file://" + tiledb::sm::Posix::current_dir() + "/tiledb_test/"; +#endif + if (s3_supported_) + temp_dir_ = s3_bucket_name_ + "tiledb/test/"; + // Exclufing those as this test creates too many arrays on HDFS + // and becomes extremely slow + // if (hdfs_supported_) + // temp_dir_ = "hdfs:///tiledb_test/"; + create_dir(temp_dir_, ctx_, vfs_); + + array_name_ = temp_dir_ + ARRAY_NAME; + int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_); + CHECK(rc == TILEDB_OK); +} + +SubarrayPartitionerDenseFx::~SubarrayPartitionerDenseFx() { + tiledb_array_free(&array_); + remove_dir(temp_dir_, ctx_, vfs_); + tiledb_ctx_free(&ctx_); + tiledb_vfs_free(&vfs_); +} + +/* ********************************* */ +/* TESTS */ +/* ********************************* */ + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, empty array", + "[SubarrayPartitioner][dense][1D][1R][empty_array]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + // Create partitioner, not done yet, current is empty + SubarrayPartitioner subarray_partitioner(subarray); + CHECK(!subarray_partitioner.done()); + auto partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + bool unsplittable; + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 100}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, whole subarray fits", + "[SubarrayPartitioner][dense][1D][1R][whole_subarray_fits]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + // --- Without budget --- + + // Create partitioner, not done yet, current is empty + SubarrayPartitioner subarray_partitioner(subarray); + CHECK(!subarray_partitioner.done()); + auto partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + bool unsplittable; + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 6}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + // --- With budget --- + + // Create partitioner, not done yet, current is empty + subarray_partitioner = SubarrayPartitioner(subarray); + + // Set budget + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + // Check again + CHECK(!subarray_partitioner.done()); + partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 6}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, split once", + "[SubarrayPartitioner][dense][1D][1R][split_once]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 5}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{2, 3}}, {{4, 5}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions = {{{2, 2}}, {{3, 5}}}; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, unsplittable at once", + "[SubarrayPartitioner][dense][1D][1R][unsplittable_at_once]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{4, 4}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, split multiple", + "[SubarrayPartitioner][dense][1D][1R][split_multiple]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 6}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = { + {{1, 2}}, {{3, 3}}, {{4, 5}}, {{6, 6}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions = {{{1, 2}}, {{3, 4}}, {{5, 6}}}; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, unsplittable after " + "multiple", + "[SubarrayPartitioner][dense][1D][1R][unsplittable_after_multiple]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 6}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, unsplittable but ok after " + "budget reset", + "[SubarrayPartitioner][dense][1D][1R][unsplittable_but_then_ok]") { + uint64_t domain[] = {1, 6}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 6}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{2, 2}}}; + std::vector> partitions_after = { + {{3, 3}}, {{4, 4}}, {{5, 6}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions_after = {{{3, 6}}}; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + st = subarray_partitioner.set_result_budget("b", 100, 100); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions_after, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, multi-range, whole subarray fits", + "[SubarrayPartitioner][dense][1D][MR][whole_subarray_fits]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 3, 5, 8, 9, 10}}; + std::vector> partitions = {{{2, 3, 5, 8, 9, 10}}}; + Layout subarray_layout = Layout::ROW_MAJOR; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, multi-range, split once", + "[SubarrayPartitioner][dense][1D][MR][split_once]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 3, 5, 8, 9, 10}}; + std::vector> partitions = {{{2, 3, 5, 8}}, + {{9, 10}}}; + Layout subarray_layout = Layout::ROW_MAJOR; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 7 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, multi-range, split multiple", + "[SubarrayPartitioner][dense][1D][MR][split_multiple]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 3, 5, 8, 9, 10}}; + std::vector> partitions = { + {{2, 3}}, {{5, 8}}, {{9, 10}}}; + Layout subarray_layout = Layout::ROW_MAJOR; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 4 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, multi-range, split multiple finer", + "[SubarrayPartitioner][dense][1D][MR][split_multiple_finer]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 3, 5, 8, 9, 10}}; + std::vector> partitions = { + {{2, 3}}, {{5, 6}}, {{7, 8}}, {{9, 10}}}; + Layout subarray_layout = Layout::ROW_MAJOR; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, multi-range, unsplittable", + "[SubarrayPartitioner][dense][1D][MR][unsplittable]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 3, 5, 8, 9, 10}}; + std::vector> partitions = {{{2, 2}}}; + Layout subarray_layout = Layout::ROW_MAJOR; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 0 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 1D, single-range, memory budget", + "[SubarrayPartitioner][dense][1D][1R][memory_budget]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = { + {{1, 2}}, + {{3, 3}}, + {{4, 4}}, + {{5, 5}}, + {{6, 6}}, + {{7, 7}}, + {{8, 8}}, + {{9, 10}}, + }; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{1, 2}}, + {{3, 4}}, + {{5, 6}}, + {{7, 8}}, + {{9, 10}}, + }; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 10000, 10000); + CHECK(st.ok()); + st = subarray_partitioner.set_memory_budget(16, 10000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, single-range, whole subarray fits", + "[SubarrayPartitioner][dense][2D][1R][whole_subarray_fits]") { + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 4}, {1, 4}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{1, 4}, {1, 4}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, single-range, unsplittable", + "[SubarrayPartitioner][dense][2D][1R][unsplittable]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {{{2, 2}, {2, 2}}}; + + SECTION("- Global order (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 4}, {2, 4}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 0); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, single-range, split multiple", + "[SubarrayPartitioner][dense][2D][1R][split_multiple]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {}; + + SECTION("- Global order (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{2, 2}, {2, 2}}, + {{2, 2}, {3, 4}}, + {{3, 4}, {2, 2}}, + {{3, 3}, {3, 4}}, + {{4, 4}, {3, 4}}, + }; + } + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Global order (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{2, 2}, {2, 2}}, + {{2, 2}, {3, 4}}, + {{3, 4}, {2, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 4}}, + }; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Global order (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{2, 2}, {2, 2}}, + {{3, 4}, {2, 2}}, + {{2, 2}, {3, 4}}, + {{3, 3}, {3, 4}}, + {{4, 4}, {3, 4}}, + }; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Global order (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{2, 2}, {2, 2}}, + {{3, 4}, {2, 2}}, + {{2, 2}, {3, 4}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 4}}, + }; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 4}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 4}}, + {{4, 4}, {2, 3}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{2, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{2, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{2, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 4}, {2, 4}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, multi-range, whole_subarray_fits", + "[SubarrayPartitioner][dense][2D][MR][whole_subarray_fits]") { + Layout subarray_layout = Layout::ROW_MAJOR; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}}; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 1000000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, multi-range, split once", + "[SubarrayPartitioner][dense][2D][MR][split_once]") { + Layout subarray_layout = Layout::ROW_MAJOR; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {}; + SubarrayRanges ranges = {}; + uint64_t budget = 0; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 2, 3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 12 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 9 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 2, 3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 12 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 4}, {1, 2, 3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 12 * sizeof(int); + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", budget); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, multi-range, calibrate", + "[SubarrayPartitioner][dense][2D][MR][calibrate]") { + Layout subarray_layout = Layout::ROW_MAJOR; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {}; + SubarrayRanges ranges = {}; + uint64_t budget = 0; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, + {{1, 2, 3, 4}, {3, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 10 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 11 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, + {{1, 2, 3, 4}, {3, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 10 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, + {{1, 2, 3, 4}, {3, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 10 * sizeof(int); + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", budget); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, multi-range, split multiple finer", + "[SubarrayPartitioner][dense][2D][MR][split_multiple_finer]") { + Layout subarray_layout = Layout::ROW_MAJOR; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {}; + SubarrayRanges ranges = {}; + uint64_t budget = 0; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 3, 4, 4}}, + {{2, 2}, {2, 3, 4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{1, 2, 3, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{1, 2, 3, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 1}, {2, 3}}, + {{2, 2}, {2, 3}}, + {{1, 2}, {4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 3, 4, 4}}, + {{2, 2}, {2, 3, 4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{1, 2, 3, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{1, 2, 3, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2}, {2, 2}}, + {{1, 2}, {3, 3}}, + {{3, 3}, {2, 3}}, + {{4, 4}, {2, 3}}, + {{1, 2, 3, 3}, {4, 4}}, + {{4, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 3, 4, 4}}, + {{2, 2}, {2, 3, 4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 1}}, + {{1, 2, 3, 4}, {2, 2}}, + {{1, 2, 3, 4}, {3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 4 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 1}, {2, 3}}, + {{2, 2}, {2, 3}}, + {{1, 2}, {4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 3, 4, 4}}, + {{2, 2}, {2, 3, 4, 4}}, + {{3, 3}, {2, 3, 4, 4}}, + {{4, 4}, {2, 3, 4, 4}}, + }; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + budget = 3 * sizeof(int); + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 4}, {1, 1}}, + {{1, 2, 3, 4}, {2, 2}}, + {{1, 2, 3, 4}, {3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 4 * sizeof(int); + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2}, {1, 2}}, + {{3, 4}, {1, 2}}, + {{1, 2, 3, 4}, {3, 3}}, + {{1, 2, 3, 4}, {4, 4}}, + }; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 3, 4, 4}}; + budget = 4 * sizeof(int); + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", budget); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerDenseFx, + "SubarrayPartitioner (Dense): 2D, multi-range, unsplittable", + "[SubarrayPartitioner][dense][2D][MR][unsplittable]") { + Layout subarray_layout = Layout::ROW_MAJOR; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {{{1, 1}, {2, 2}}}; + SubarrayRanges ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 4}}; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 4}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 17 * sizeof(int), + 20 * sizeof(int), + 21 * sizeof(int), + 23 * sizeof(int), + 24 * sizeof(int), + 25 * sizeof(int), + 27 * sizeof(int), + 28 * sizeof(int), + 29 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, + 10, 11, 12, 13, 13, 14, 15, 16, 16}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_GLOBAL_ORDER, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 0); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} diff --git a/test/src/unit-SubarrayPartitioner-error.cc b/test/src/unit-SubarrayPartitioner-error.cc new file mode 100644 index 000000000000..bc36698d464e --- /dev/null +++ b/test/src/unit-SubarrayPartitioner-error.cc @@ -0,0 +1,220 @@ +/** + * @file unit-SubarrayPartitioner-error.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2017-2019 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * Tests the `SubarrayPartitioner` class for errors. + */ + +#include "test/src/helpers.h" +#include "tiledb/sm/c_api/tiledb_struct_def.h" +#include "tiledb/sm/subarray/subarray_partitioner.h" + +#ifdef _WIN32 +#include "tiledb/sm/filesystem/win.h" +#else +#include "tiledb/sm/filesystem/posix.h" +#endif + +#include +#include + +using namespace tiledb::sm; + +/* ********************************* */ +/* STRUCT DEFINITION */ +/* ********************************* */ + +struct SubarrayPartitionerErrorFx { + tiledb_ctx_t* ctx_; + tiledb_vfs_t* vfs_; + bool s3_supported_, hdfs_supported_; + std::string temp_dir_; + const std::string s3_bucket_name_ = + "s3://" + random_bucket_name("tiledb") + "/"; + std::string array_name_; + const char* ARRAY_NAME = "subarray_partitioner_error"; + tiledb_array_t* array_ = nullptr; + + SubarrayPartitionerErrorFx(); + ~SubarrayPartitionerErrorFx(); +}; + +SubarrayPartitionerErrorFx::SubarrayPartitionerErrorFx() { + ctx_ = nullptr; + vfs_ = nullptr; + hdfs_supported_ = false; + s3_supported_ = false; + + get_supported_fs(&s3_supported_, &hdfs_supported_); + create_ctx_and_vfs(s3_supported_, &ctx_, &vfs_); + create_s3_bucket(s3_bucket_name_, s3_supported_, ctx_, vfs_); + +// Create temporary directory based on the supported filesystem +#ifdef _WIN32 + temp_dir_ = tiledb::sm::Win::current_dir() + "\\tiledb_test\\"; +#else + temp_dir_ = "file://" + tiledb::sm::Posix::current_dir() + "/tiledb_test/"; +#endif + if (s3_supported_) + temp_dir_ = s3_bucket_name_ + "tiledb/test/"; + if (hdfs_supported_) + temp_dir_ = "hdfs:///tiledb_test/"; + create_dir(temp_dir_, ctx_, vfs_); + + array_name_ = temp_dir_ + ARRAY_NAME; + int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_); + CHECK(rc == TILEDB_OK); +} + +SubarrayPartitionerErrorFx::~SubarrayPartitionerErrorFx() { + tiledb_array_free(&array_); + remove_dir(temp_dir_, ctx_, vfs_); + tiledb_ctx_free(&ctx_); + tiledb_vfs_free(&vfs_); +} + +/* ********************************* */ +/* TESTS */ +/* ********************************* */ + +TEST_CASE_METHOD( + SubarrayPartitionerErrorFx, + "SubarrayPartitioner (Error): 1D, result and memory budget, " + "setters/getters", + "[SubarrayPartitioner][error][1D][budget][set_get]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_DENSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + SubarrayPartitioner subarray_partitioner(subarray); + uint64_t budget, budget_off, budget_val; + + auto st = subarray_partitioner.get_result_budget("a", &budget); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget(nullptr, 10); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("foo", 10); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("a", 10, 10); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("a", 10); + CHECK(st.ok()); + st = subarray_partitioner.get_result_budget(nullptr, &budget); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("foo", &budget); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("a", &budget_off, &budget_val); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("a", &budget); + CHECK(st.ok()); + CHECK(budget == 10); + st = subarray_partitioner.get_result_budget(TILEDB_COORDS, &budget); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 11); + CHECK(st.ok()); + st = subarray_partitioner.get_result_budget(TILEDB_COORDS, &budget); + CHECK(st.ok()); + CHECK(budget == 11); + st = subarray_partitioner.get_result_budget("b", &budget_off, &budget_val); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget(nullptr, 100, 101); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("foo", 100, 101); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("foo", 100); + CHECK(!st.ok()); + st = subarray_partitioner.set_result_budget("b", 100, 101); + CHECK(st.ok()); + st = + subarray_partitioner.get_result_budget(nullptr, &budget_off, &budget_val); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("foo", &budget_off, &budget_val); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("b", &budget); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget("b", &budget_off, &budget_val); + CHECK(st.ok()); + CHECK(budget_off == 100); + CHECK(budget_val == 101); + st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 100, 101); + CHECK(!st.ok()); + st = subarray_partitioner.get_result_budget( + TILEDB_COORDS, &budget_off, &budget_val); + CHECK(!st.ok()); + + uint64_t memory_budget, memory_budget_var; + st = subarray_partitioner.get_memory_budget( + &memory_budget, &memory_budget_var); + CHECK(memory_budget == 5368709120); + CHECK(memory_budget_var == 10737418240); + st = subarray_partitioner.set_memory_budget(16, 16); + st = subarray_partitioner.get_memory_budget( + &memory_budget, &memory_budget_var); + CHECK(memory_budget == 16); + CHECK(memory_budget_var == 16); + + close_array(ctx_, array_); +} diff --git a/test/src/unit-SubarrayPartitioner-sparse.cc b/test/src/unit-SubarrayPartitioner-sparse.cc new file mode 100644 index 000000000000..ce6c7bdca0a9 --- /dev/null +++ b/test/src/unit-SubarrayPartitioner-sparse.cc @@ -0,0 +1,2857 @@ +/** + * @file unit-SubarrayPartitioner-sparse.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2017-2019 TileDB, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * Tests the `SubarrayPartitioner` class for sparse arrays. + */ + +#include "test/src/helpers.h" +#include "tiledb/sm/c_api/tiledb_struct_def.h" +#include "tiledb/sm/subarray/subarray_partitioner.h" + +#ifdef _WIN32 +#include "tiledb/sm/filesystem/win.h" +#else +#include "tiledb/sm/filesystem/posix.h" +#endif + +#include +#include + +using namespace tiledb::sm; + +/* ********************************* */ +/* STRUCT DEFINITION */ +/* ********************************* */ + +struct SubarrayPartitionerSparseFx { + tiledb_ctx_t* ctx_; + tiledb_vfs_t* vfs_; + bool s3_supported_, hdfs_supported_; + std::string temp_dir_; + const std::string s3_bucket_name_ = + "s3://" + random_bucket_name("tiledb") + "/"; + std::string array_name_; + const char* ARRAY_NAME = "subarray_partitioner_sparse"; + tiledb_array_t* array_ = nullptr; + + SubarrayPartitionerSparseFx(); + ~SubarrayPartitionerSparseFx(); +}; + +SubarrayPartitionerSparseFx::SubarrayPartitionerSparseFx() { + ctx_ = nullptr; + vfs_ = nullptr; + hdfs_supported_ = false; + s3_supported_ = false; + + get_supported_fs(&s3_supported_, &hdfs_supported_); + create_ctx_and_vfs(s3_supported_, &ctx_, &vfs_); + create_s3_bucket(s3_bucket_name_, s3_supported_, ctx_, vfs_); + +// Create temporary directory based on the supported filesystem +#ifdef _WIN32 + temp_dir_ = tiledb::sm::Win::current_dir() + "\\tiledb_test\\"; +#else + temp_dir_ = "file://" + tiledb::sm::Posix::current_dir() + "/tiledb_test/"; +#endif + if (s3_supported_) + temp_dir_ = s3_bucket_name_ + "tiledb/test/"; + // Exclufing those as this test creates too many arrays on HDFS + // and becomes extremely slow + // if (hdfs_supported_) + // temp_dir_ = "hdfs:///tiledb_test/"; + create_dir(temp_dir_, ctx_, vfs_); + + array_name_ = temp_dir_ + ARRAY_NAME; + int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_); + CHECK(rc == TILEDB_OK); +} + +SubarrayPartitionerSparseFx::~SubarrayPartitionerSparseFx() { + tiledb_array_free(&array_); + remove_dir(temp_dir_, ctx_, vfs_); + tiledb_ctx_free(&ctx_); + tiledb_vfs_free(&vfs_); +} + +/* ********************************* */ +/* TESTS */ +/* ********************************* */ + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, empty array", + "[SubarrayPartitioner][sparse][1D][1R][empty_array]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + // Create partitioner, not done yet, current is empty + SubarrayPartitioner subarray_partitioner(subarray); + CHECK(!subarray_partitioner.done()); + auto partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + bool unsplittable; + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 100}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, whole subarray fits", + "[SubarrayPartitioner][sparse][1D][1R][whole_subarray_fits]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + // --- Without budget --- + + // Create partitioner, not done yet, current is empty + SubarrayPartitioner subarray_partitioner(subarray); + CHECK(!subarray_partitioner.done()); + auto partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + bool unsplittable; + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 100}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + // --- With budget --- + + // Create partitioner, not done yet, current is empty + subarray_partitioner = SubarrayPartitioner(subarray); + + // Set budget + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + // Check again + CHECK(!subarray_partitioner.done()); + partition = subarray_partitioner.current(); + CHECK(partition.range_num() == 0); + + // Get next, it should not be unsplittable + subarray_partitioner.next(&unsplittable); + CHECK(!unsplittable); + + // Get and check current, should contain a single range (whole domain) + partition = subarray_partitioner.current(); + check_subarray(partition, {{1, 100}}); + + // Partitioner should be done + CHECK(subarray_partitioner.done()); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, split once", + "[SubarrayPartitioner][sparse][1D][1R][split_once]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{3, 11}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{3, 7}}, {{8, 11}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions = {{{3, 6}}, {{7, 10}}, {{11, 11}}}; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable at once", + "[SubarrayPartitioner][sparse][1D][1R][unsplittable_at_once]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{4, 4}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions{}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, split multiple", + "[SubarrayPartitioner][sparse][1D][1R][split_multiple]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 18}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = { + {{2, 4}}, {{5, 6}}, {{7, 10}}, {{11, 18}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable after " + "multiple", + "[SubarrayPartitioner][sparse][1D][1R][unsplittable_after_multiple]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 18}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 3 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable but ok after " + "budget reset", + "[SubarrayPartitioner][sparse][1D][1R][unsplittable_but_then_ok]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2, 18}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{2, 2}}}; + std::vector> partitions_after = { + {{3, 3}}, {{4, 4}}, {{5, 6}}, {{7, 10}}, {{11, 18}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 1, 1); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + st = subarray_partitioner.set_result_budget("b", 100, 100); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions_after, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, float, split multiple", + "[SubarrayPartitioner][sparse][1D][1R][float][split_multiple]") { + float domain[] = {1.0f, 100.0f}; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_FLOAT32}, + {domain}, + {nullptr}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + auto max = std::numeric_limits::max(); + AttrBuffers attr_buffers; + std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; + uint64_t coords_size = coords.size() * sizeof(float); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2.0f, 18.0f}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = { + {{2.0f, 4.0f}}, + {{std::nextafter(4.0f, max), 6.0f}}, + {{std::nextafter(6.0f, max), 10.0f}}, + {{std::nextafter(10.0f, max), 18.0f}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, float, unsplittable after " + "multiple", + "[SubarrayPartitioner][sparse][1D][1R][float][unsplittable_after_" + "multiple]") { + float domain[] = {1.0f, 100.0f}; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_FLOAT32}, + {domain}, + {nullptr}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; + uint64_t coords_size = coords.size() * sizeof(float); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2.0f, 18.0f}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{2.0f, 2.0f}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 0, 0); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, float, whole subarray " + "fits", + "[SubarrayPartitioner][sparse][1D][1R][float][whole_subarray_fits]") { + float domain[] = {1.0f, 100.0f}; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_FLOAT32}, + {domain}, + {nullptr}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; + uint64_t coords_size = coords.size() * sizeof(float); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{2.0f, 18.0f}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{2.0f, 18.0f}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 10000, 10000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, single-range, memory budget", + "[SubarrayPartitioner][sparse][1D][1R][memory_budget]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = { + {{1, 4}}, + {{5, 7}}, + {{8, 10}}, + {{11, 13}}, + {{14, 19}}, + {{20, 25}}, + {{26, 32}}, + {{33, 38}}, + {{39, 50}}, + {{51, 100}}, + }; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{1, 3}}, + {{4, 4}}, + {{5, 5}}, + {{6, 10}}, + {{11, 20}}, + {{21, 30}}, + {{31, 40}}, + {{41, 100}}, + }; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 10000, 10000); + CHECK(st.ok()); + st = subarray_partitioner.set_memory_budget(16, 10000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, multi-range, whole subarray fits", + "[SubarrayPartitioner][sparse][1D][MR][whole_subarray_fits]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{5, 10, 25, 27, 33, 50}}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = { + {{5, 10, 25, 27, 33, 50}}}; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, multi-range, split once", + "[SubarrayPartitioner][sparse][1D][MR][split_once]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{5, 10, 25, 27, 33, 50}}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = {{{5, 10, 25, 27}}, + {{33, 50}}}; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 4 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, multi-range, split multiple", + "[SubarrayPartitioner][sparse][1D][MR][split_multiple]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{5, 10, 25, 27, 33, 50}}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = { + {{5, 10}}, {{25, 27}}, {{33, 50}}}; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int)); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, multi-range, split multiple finer", + "[SubarrayPartitioner][sparse][1D][MR][split_multiple_finer]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{5, 10, 25, 27, 33, 40}}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = { + {{5, 7}}, + {{8, 10}}, + {{25, 26}}, + {{27, 27}}, + {{33, 36}}, + {{37, 40}}, + }; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 2 * sizeof(int) - 1); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 1D, multi-range, unsplittable", + "[SubarrayPartitioner][sparse][1D][MR][unsplittable]") { + uint64_t domain[] = {1, 100}; + uint64_t tile_extent = 10; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d"}, + {TILEDB_UINT64}, + {domain}, + {&tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int), + 15 * sizeof(int), + 16 * sizeof(int), + 17 * sizeof(int), + 18 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = { + 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{5, 10, 25, 27, 33, 40}}; + Layout subarray_layout = Layout::ROW_MAJOR; + std::vector> partitions = {{{5, 5}}}; + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 1); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, single-range, whole subarray fits", + "[SubarrayPartitioner][sparse][2D][1R][whole_subarray_fits]") { + uint64_t domain[] = {1, 10}; + uint64_t tile_extent = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent, &tile_extent}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + TILEDB_ROW_MAJOR, + TILEDB_ROW_MAJOR, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 10}, {1, 10}}; + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{1, 10}, {1, 10}}}; + + SECTION("- Global order") { + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major") { + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major") { + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered") { + subarray_layout = Layout::UNORDERED; + } + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 100000); + CHECK(st.ok()); + st = subarray_partitioner.set_result_budget("b", 100000, 100000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, single-range, split multiple", + "[SubarrayPartitioner][sparse][2D][1R][split_multiple]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + + SECTION("- Global order (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{3, 3}, {1, 2}}, + {{4, 4}, {1, 2}}, + {{3, 4}, {3, 4}}, + {{3, 4}, {5, 6}}, + {{3, 3}, {7, 8}}, + {{4, 4}, {7, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{3, 3}, {1, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{3, 4}, {1, 1}}, + {{3, 4}, {2, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{3, 3}, {1, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Global order (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{3, 4}, {1, 1}}, + {{3, 4}, {2, 2}}, + {{3, 4}, {3, 4}}, + {{3, 4}, {5, 6}}, + {{3, 4}, {7, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{3, 3}, {1, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{3, 4}, {1, 1}}, + {{3, 4}, {2, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{3, 4}, {1, 1}}, + {{3, 4}, {2, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Global order (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{3, 4}, {1, 2}}, + {{3, 4}, {3, 4}}, + {{3, 4}, {5, 6}}, + {{3, 3}, {7, 8}}, + {{4, 4}, {7, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{3, 3}, {1, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{3, 4}, {1, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{3, 3}, {1, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Global order (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + partitions = { + {{3, 4}, {1, 2}}, + {{3, 4}, {3, 4}}, + {{3, 4}, {5, 6}}, + {{3, 4}, {7, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{3, 3}, {1, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 10}}, + {{4, 4}, {1, 5}}, + {{4, 4}, {6, 10}}, + }; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{3, 4}, {1, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{3, 4}, {1, 2}}, + {{3, 4}, {3, 3}}, + {{3, 4}, {4, 5}}, + {{3, 4}, {6, 7}}, + {{3, 4}, {8, 8}}, + {{3, 4}, {9, 10}}, + }; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{3, 4}, {1, 10}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget( + TILEDB_COORDS, 2 * sizeof(uint64_t)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, single-range, unsplittable", + "[SubarrayPartitioner][sparse][2D][1R][unsplittable]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{1, 1}, {1, 1}}}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + + SECTION("- Global order (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Global order (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::GLOBAL_ORDER; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 1, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 10}, {1, 10}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 0); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, multi-range, whole subarray fits", + "[SubarrayPartitioner][sparse][2D][MR][whole_subarray_fits]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 5}}}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 1, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 5}}; + + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 10000); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, multi-range, split once", + "[SubarrayPartitioner][sparse][2D][MR][split_once]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + SubarrayRanges ranges; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, {{1, 2, 3, 4}, {3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, {{1, 2, 3, 4}, {3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = { + {{1, 2, 3, 4}, {1, 2}}, {{1, 2, 3, 4}, {3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 4 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +/** + * Tests subarray range calibration, such that the ranges involved + * in the next partition fall in the same slab (or fall in a single + * slab in case the subarray layout is UNORDERED). + */ +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, multi-range, calibrate", + "[SubarrayPartitioner][sparse][2D][MR][calibrate]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + SubarrayRanges ranges; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}}; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}}; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}}; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}}; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}}; + partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}}; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 5 * sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, multi-range, unsplittable", + "[SubarrayPartitioner][sparse][2D][MR][unsplittable]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + std::vector> partitions = {{{1, 1}, {2, 2}}}; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + SubarrayRanges ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", 0); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, true); + + close_array(ctx_, array_); +} + +TEST_CASE_METHOD( + SubarrayPartitionerSparseFx, + "SubarrayPartitioner (Sparse): 2D, multi-range, split multiple finer", + "[SubarrayPartitioner][sparse][2D][MR][split_multiple_finer]") { + Layout subarray_layout = Layout::GLOBAL_ORDER; + tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; + tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; + std::vector> partitions = {}; + + SECTION("- Row-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 5, 6, 9}}, + {{2, 2}, {2, 5, 6, 9}}, + {{3, 3}, {2, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Col-major (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{1, 2, 3, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 5}}, + {{1, 2, 3, 3, 4, 4}, {6, 7}}, + {{1, 2, 3, 3, 4, 4}, {8, 8}}, + {{1, 2, 3, 3, 4, 4}, {9, 9}}, + }; + } + + SECTION("- Unordered (tile: row, cell: row)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 1}, {2, 5}}, + {{2, 2}, {2, 5}}, + {{1, 2}, {6, 9}}, + {{3, 3}, {2, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Row-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 5, 6, 9}}, + {{2, 2}, {2, 5, 6, 9}}, + {{3, 3}, {2, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Col-major (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3}, {2, 2}}, + {{4, 4}, {2, 2}}, + {{1, 2, 3, 3}, {3, 3}}, + {{4, 4}, {3, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 5}}, + {{1, 2, 3, 3, 4, 4}, {6, 7}}, + {{1, 2, 3, 3, 4, 4}, {8, 8}}, + {{1, 2, 3, 3, 4, 4}, {9, 9}}, + }; + } + + SECTION("- Unordered (tile: row, cell: col)") { + tile_order = TILEDB_ROW_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2}, {2, 3}}, + {{1, 2}, {4, 5}}, + {{3, 3}, {2, 5}}, + {{4, 4}, {2, 5}}, + {{1, 2, 3, 3}, {6, 9}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Row-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 5, 6, 9}}, + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 5}}, + {{2, 2}, {6, 9}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Col-major (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 2}}, + {{1, 2, 3, 3, 4, 4}, {3, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + {{1, 2, 3, 3, 4, 4}, {5, 5}}, + {{1, 2, 3, 3, 4, 4}, {6, 7}}, + {{1, 2, 3, 3, 4, 4}, {8, 8}}, + {{1, 2, 3, 3, 4, 4}, {9, 9}}, + }; + } + + SECTION("- Unordered (tile: col, cell: row)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_ROW_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 1}, {2, 5}}, + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 5}}, + {{1, 2}, {6, 9}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Row-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::ROW_MAJOR; + partitions = { + {{1, 1}, {2, 5, 6, 9}}, + {{2, 2}, {2, 3}}, + {{2, 2}, {4, 5}}, + {{2, 2}, {6, 9}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 5}}, + {{3, 3}, {6, 9}}, + {{4, 4}, {2, 5}}, + {{4, 4}, {6, 9}}, + }; + } + + SECTION("- Col-major (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::COL_MAJOR; + partitions = { + {{1, 2, 3, 3, 4, 4}, {2, 2}}, + {{1, 2, 3, 3, 4, 4}, {3, 3}}, + {{1, 2, 3, 3, 4, 4}, {4, 4}}, + {{1, 2, 3, 3, 4, 4}, {5, 5}}, + {{1, 2, 3, 3, 4, 4}, {6, 7}}, + {{1, 2, 3, 3, 4, 4}, {8, 8}}, + {{1, 2, 3, 3, 4, 4}, {9, 9}}, + }; + } + + SECTION("- Unordered (tile: col, cell: col)") { + tile_order = TILEDB_COL_MAJOR; + cell_order = TILEDB_COL_MAJOR; + subarray_layout = Layout::UNORDERED; + partitions = { + {{1, 2}, {2, 3}}, + {{1, 2}, {4, 5}}, + {{3, 3}, {2, 3}}, + {{3, 3}, {4, 5}}, + {{4, 4}, {2, 5}}, + {{1, 2, 3, 3}, {6, 9}}, + {{4, 4}, {6, 9}}, + }; + } + + uint64_t domain[] = {1, 10}; + uint64_t tile_extent_1 = 2; + uint64_t tile_extent_2 = 2; + create_array( + ctx_, + array_name_, + TILEDB_SPARSE, + {"d1", "d2"}, + {TILEDB_UINT64, TILEDB_UINT64}, + {domain, domain}, + {&tile_extent_1, &tile_extent_2}, + {"a", "b"}, + {TILEDB_INT32, TILEDB_INT32}, + {1, TILEDB_VAR_NUM}, + {::Compressor(TILEDB_FILTER_LZ4, -1), + ::Compressor(TILEDB_FILTER_LZ4, -1)}, + tile_order, + cell_order, + 2); + + AttrBuffers attr_buffers; + std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; + uint64_t coords_size = coords.size() * sizeof(uint64_t); + std::vector a = {1, 2, 3, 4, 5, 6}; + uint64_t a_size = a.size() * sizeof(int); + std::vector b_off = {0, + sizeof(int), + 3 * sizeof(int), + 6 * sizeof(int), + 9 * sizeof(int), + 11 * sizeof(int)}; + uint64_t b_off_size = b_off.size() * sizeof(uint64_t); + std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; + uint64_t b_val_size = b_val.size() * sizeof(int); + attr_buffers[TILEDB_COORDS] = + AttrBuffer({&coords[0], coords_size, nullptr, 0}); + attr_buffers["a"] = AttrBuffer({&a[0], a_size, nullptr, 0}); + attr_buffers["b"] = + AttrBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size}); + write_array(ctx_, array_name_, TILEDB_UNORDERED, attr_buffers); + + open_array(ctx_, array_, TILEDB_READ); + + Subarray subarray; + SubarrayRanges ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}; + create_subarray(array_->array_, ranges, subarray_layout, &subarray); + + SubarrayPartitioner subarray_partitioner(subarray); + auto st = subarray_partitioner.set_result_budget("a", sizeof(int)); + CHECK(st.ok()); + + check_partitions(subarray_partitioner, partitions, false); + + close_array(ctx_, array_); +} diff --git a/test/src/unit-capi-subarray_partitioner.cc b/test/src/unit-capi-subarray_partitioner.cc deleted file mode 100644 index 8c8a5fc3abad..000000000000 --- a/test/src/unit-capi-subarray_partitioner.cc +++ /dev/null @@ -1,9187 +0,0 @@ -/** - * @file unit-capi-subarray_partitioner.cc - * - * @section LICENSE - * - * The MIT License - * - * @copyright Copyright (c) 2017-2018 TileDB Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @section DESCRIPTION - * - * Tests the C API for subarray partitioner. - */ - -#include "catch.hpp" -#include "test/src/helpers.h" -#include "tiledb/sm/c_api/tiledb.h" - -#include -#include -#include - -/** Tests for C API subarray partitioner. */ -struct SubarrayPartitionerFx { - // TileDB context - tiledb_ctx_t* ctx_; - - // Constructors/destructor - SubarrayPartitionerFx(); - ~SubarrayPartitionerFx(); - - // Functions - void create_sparse_array_1d( - const std::string& array_name, const uint64_t* dim_domain); - void create_sparse_array_2d( - const std::string& array_name, - const uint64_t* dim_domain, - tiledb_layout_t layout); - void create_dense_array_1d( - const std::string& array_name, - const uint64_t* dim_domain, - uint64_t tile_extent); - void create_dense_array_2d( - const std::string& array_name, - const uint64_t* dim_domain, - uint64_t tile_extent, - tiledb_layout_t cell_order, - tiledb_layout_t tile_order); - template - void write_sparse_array( - const std::string& array_name, - const std::vector& coords, - const std::vector& a, - const std::vector& b_off, - const std::vector& b_val); - template - void write_dense_array( - const std::string& array_name, - const std::vector& subarray, - const std::vector& a, - const std::vector& b_off, - const std::vector& b_val); - void create_sparse_array_1d_float( - const std::string& array_name, const float* dim_domain); - void remove_array(const std::string& array_name); - bool is_array(const std::string& array_name); -}; - -SubarrayPartitionerFx::SubarrayPartitionerFx() { - ctx_ = nullptr; - REQUIRE(tiledb_ctx_alloc(nullptr, &ctx_) == TILEDB_OK); -} - -SubarrayPartitionerFx::~SubarrayPartitionerFx() { - tiledb_ctx_free(&ctx_); - CHECK(ctx_ == nullptr); -} - -bool SubarrayPartitionerFx::is_array(const std::string& array_name) { - tiledb_object_t type = TILEDB_INVALID; - REQUIRE(tiledb_object_type(ctx_, array_name.c_str(), &type) == TILEDB_OK); - return type == TILEDB_ARRAY || type == TILEDB_KEY_VALUE; -} - -void SubarrayPartitionerFx::remove_array(const std::string& array_name) { - if (!is_array(array_name)) - return; - - CHECK(tiledb_object_remove(ctx_, array_name.c_str()) == TILEDB_OK); -} - -void SubarrayPartitionerFx::create_sparse_array_1d( - const std::string& array_name, const uint64_t* dim_domain) { - // Create dimensions - uint64_t tile_extents[] = {10}; - tiledb_dimension_t* d; - int rc = tiledb_dimension_alloc( - ctx_, "d", TILEDB_UINT64, &dim_domain[0], &tile_extents[0], &d); - CHECK(rc == TILEDB_OK); - - // Create domain - tiledb_domain_t* domain; - rc = tiledb_domain_alloc(ctx_, &domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d); - CHECK(rc == TILEDB_OK); - - // Create attributes - tiledb_attribute_t* a; - rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, a, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, a, 1); - CHECK(rc == TILEDB_OK); - tiledb_attribute_t* b; - rc = tiledb_attribute_alloc(ctx_, "b", TILEDB_INT32, &b); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, b, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, b, TILEDB_VAR_NUM); - CHECK(rc == TILEDB_OK); - - // Create array schmea - tiledb_array_schema_t* array_schema; - rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 2); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, b); - CHECK(rc == TILEDB_OK); - - // Check array schema - rc = tiledb_array_schema_check(ctx_, array_schema); - CHECK(rc == TILEDB_OK); - - // Create array - rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_attribute_free(&a); - tiledb_attribute_free(&b); - tiledb_dimension_free(&d); - tiledb_domain_free(&domain); - tiledb_array_schema_free(&array_schema); -} - -void SubarrayPartitionerFx::create_dense_array_1d( - const std::string& array_name, - const uint64_t* dim_domain, - uint64_t tile_extent) { - // Create dimensions - tiledb_dimension_t* d; - int rc = tiledb_dimension_alloc( - ctx_, "d", TILEDB_UINT64, &dim_domain[0], &tile_extent, &d); - CHECK(rc == TILEDB_OK); - - // Create domain - tiledb_domain_t* domain; - rc = tiledb_domain_alloc(ctx_, &domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d); - CHECK(rc == TILEDB_OK); - - // Create attributes - tiledb_attribute_t* a; - rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, a, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, a, 1); - CHECK(rc == TILEDB_OK); - tiledb_attribute_t* b; - rc = tiledb_attribute_alloc(ctx_, "b", TILEDB_INT32, &b); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, b, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, b, TILEDB_VAR_NUM); - CHECK(rc == TILEDB_OK); - - // Create array schema - tiledb_array_schema_t* array_schema; - rc = tiledb_array_schema_alloc(ctx_, TILEDB_DENSE, &array_schema); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 2); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, b); - CHECK(rc == TILEDB_OK); - - // Check array schema - rc = tiledb_array_schema_check(ctx_, array_schema); - CHECK(rc == TILEDB_OK); - - // Create array - rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_attribute_free(&a); - tiledb_attribute_free(&b); - tiledb_dimension_free(&d); - tiledb_domain_free(&domain); - tiledb_array_schema_free(&array_schema); -} - -void SubarrayPartitionerFx::create_sparse_array_2d( - const std::string& array_name, - const uint64_t* dim_domain, - tiledb_layout_t layout) { - // Create dimensions - uint64_t tile_extents[] = {10, 10}; - tiledb_dimension_t* d1; - int rc = tiledb_dimension_alloc( - ctx_, "d1", TILEDB_UINT64, &dim_domain[0], &tile_extents[0], &d1); - CHECK(rc == TILEDB_OK); - tiledb_dimension_t* d2; - rc = tiledb_dimension_alloc( - ctx_, "d2", TILEDB_UINT64, &dim_domain[2], &tile_extents[1], &d2); - - // Create domain - tiledb_domain_t* domain; - rc = tiledb_domain_alloc(ctx_, &domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d1); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d2); - CHECK(rc == TILEDB_OK); - - // Create attributes - tiledb_attribute_t* a; - rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, a, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, a, 1); - CHECK(rc == TILEDB_OK); - tiledb_attribute_t* b; - rc = tiledb_attribute_alloc(ctx_, "b", TILEDB_INT32, &b); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, b, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, b, TILEDB_VAR_NUM); - CHECK(rc == TILEDB_OK); - - // Create array schmea - tiledb_array_schema_t* array_schema; - rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, layout); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 2); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, b); - CHECK(rc == TILEDB_OK); - - // Check array schema - rc = tiledb_array_schema_check(ctx_, array_schema); - CHECK(rc == TILEDB_OK); - - // Create array - rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_attribute_free(&a); - tiledb_attribute_free(&b); - tiledb_dimension_free(&d1); - tiledb_dimension_free(&d2); - tiledb_domain_free(&domain); - tiledb_array_schema_free(&array_schema); -} - -void SubarrayPartitionerFx::create_dense_array_2d( - const std::string& array_name, - const uint64_t* dim_domain, - uint64_t tile_extent, - tiledb_layout_t cell_order, - tiledb_layout_t tile_order) { - // Create dimensions - tiledb_dimension_t* d1; - int rc = tiledb_dimension_alloc( - ctx_, "d1", TILEDB_UINT64, &dim_domain[0], &tile_extent, &d1); - CHECK(rc == TILEDB_OK); - tiledb_dimension_t* d2; - rc = tiledb_dimension_alloc( - ctx_, "d2", TILEDB_UINT64, &dim_domain[2], &tile_extent, &d2); - - // Create domain - tiledb_domain_t* domain; - rc = tiledb_domain_alloc(ctx_, &domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d1); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d2); - CHECK(rc == TILEDB_OK); - - // Create attributes - tiledb_attribute_t* a; - rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, a, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, a, 1); - CHECK(rc == TILEDB_OK); - tiledb_attribute_t* b; - rc = tiledb_attribute_alloc(ctx_, "b", TILEDB_INT32, &b); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, b, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, b, TILEDB_VAR_NUM); - CHECK(rc == TILEDB_OK); - - // Create array schmea - tiledb_array_schema_t* array_schema; - rc = tiledb_array_schema_alloc(ctx_, TILEDB_DENSE, &array_schema); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, cell_order); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, tile_order); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 2); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, b); - CHECK(rc == TILEDB_OK); - - // Check array schema - rc = tiledb_array_schema_check(ctx_, array_schema); - CHECK(rc == TILEDB_OK); - - // Create array - rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_attribute_free(&a); - tiledb_attribute_free(&b); - tiledb_dimension_free(&d1); - tiledb_dimension_free(&d2); - tiledb_domain_free(&domain); - tiledb_array_schema_free(&array_schema); -} - -template -void SubarrayPartitionerFx::write_sparse_array( - const std::string& array_name, - const std::vector& coords, - const std::vector& a, - const std::vector& b_off, - const std::vector& b_val) { - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_WRITE); - CHECK(rc == TILEDB_OK); - - uint64_t coords_size = coords.size() * sizeof(T); - uint64_t a_size = a.size() * sizeof(int); - uint64_t b_off_size = b_off.size() * sizeof(uint64_t); - uint64_t b_val_size = b_val.size() * sizeof(int); - - // Create query - tiledb_query_t* query; - rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_buffer(ctx_, query, "a", (void*)a.data(), &a_size); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_buffer_var( - ctx_, - query, - "b", - (uint64_t*)b_off.data(), - &b_off_size, - (void*)b_val.data(), - &b_val_size); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_buffer( - ctx_, query, TILEDB_COORDS, (void*)coords.data(), &coords_size); - CHECK(rc == TILEDB_OK); - - // Submit query - rc = tiledb_query_submit(ctx_, query); - CHECK(rc == TILEDB_OK); - - // Finalize query - rc = tiledb_query_finalize(ctx_, query); - CHECK(rc == TILEDB_OK); - - // Close array - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_array_free(&array); - tiledb_query_free(&query); -} - -template -void SubarrayPartitionerFx::write_dense_array( - const std::string& array_name, - const std::vector& subarray, - const std::vector& a, - const std::vector& b_off, - const std::vector& b_val) { - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_WRITE); - CHECK(rc == TILEDB_OK); - - uint64_t a_size = a.size() * sizeof(int); - uint64_t b_off_size = b_off.size() * sizeof(uint64_t); - uint64_t b_val_size = b_val.size() * sizeof(int); - - // Create query - tiledb_query_t* query; - rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_subarray(ctx_, query, &subarray[0]); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_buffer(ctx_, query, "a", (void*)a.data(), &a_size); - CHECK(rc == TILEDB_OK); - rc = tiledb_query_set_buffer_var( - ctx_, - query, - "b", - (uint64_t*)b_off.data(), - &b_off_size, - (void*)b_val.data(), - &b_val_size); - CHECK(rc == TILEDB_OK); - - // Submit query - rc = tiledb_query_submit(ctx_, query); - CHECK(rc == TILEDB_OK); - - // Finalize query - rc = tiledb_query_finalize(ctx_, query); - CHECK(rc == TILEDB_OK); - - // Close array - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_array_free(&array); - tiledb_query_free(&query); -} - -void SubarrayPartitionerFx::create_sparse_array_1d_float( - const std::string& array_name, const float* dim_domain) { - // Create dimensions - tiledb_dimension_t* d; - int rc = tiledb_dimension_alloc( - ctx_, "d", TILEDB_FLOAT32, &dim_domain[0], nullptr, &d); - CHECK(rc == TILEDB_OK); - - // Create domain - tiledb_domain_t* domain; - rc = tiledb_domain_alloc(ctx_, &domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_domain_add_dimension(ctx_, domain, d); - CHECK(rc == TILEDB_OK); - - // Create attributes - tiledb_attribute_t* a; - rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &a); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, a, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, a, 1); - CHECK(rc == TILEDB_OK); - tiledb_attribute_t* b; - rc = tiledb_attribute_alloc(ctx_, "b", TILEDB_INT32, &b); - CHECK(rc == TILEDB_OK); - rc = set_attribute_compression_filter(ctx_, b, TILEDB_FILTER_LZ4, -1); - CHECK(rc == TILEDB_OK); - rc = tiledb_attribute_set_cell_val_num(ctx_, b, TILEDB_VAR_NUM); - CHECK(rc == TILEDB_OK); - - // Create array schmea - tiledb_array_schema_t* array_schema; - rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 2); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, a); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_schema_add_attribute(ctx_, array_schema, b); - CHECK(rc == TILEDB_OK); - - // Check array schema - rc = tiledb_array_schema_check(ctx_, array_schema); - CHECK(rc == TILEDB_OK); - - // Create array - rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema); - CHECK(rc == TILEDB_OK); - - // Clean up - tiledb_attribute_free(&a); - tiledb_attribute_free(&b); - tiledb_dimension_free(&d); - tiledb_domain_free(&domain); - tiledb_array_schema_free(&array_schema); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, basic API usage and errors", - "[capi], [subarray-partitioner], [subarray-partitioner-basic]") { - std::string array_name = "subarray_partitioner_basic"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - uint64_t budget, budget_off, budget_val; - - // Set/get result budget, fixed-sized - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, "a", &budget); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, nullptr, 10); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "foo", 10); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "a", 10, 10); - CHECK(rc == TILEDB_ERR); - rc = - tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 10); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, nullptr, &budget); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, "foo", &budget); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, "a", &budget_off, &budget_val); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, "a", &budget); - CHECK(rc == TILEDB_OK); - CHECK(budget == 10); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, TILEDB_COORDS, &budget); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 10); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, TILEDB_COORDS, &budget); - CHECK(rc == TILEDB_OK); - CHECK(budget == 10); - - // Set/get result budget, var-sized - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, "b", &budget_off, &budget_val); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, nullptr, 100, 101); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "foo", 100, 101); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "b", 100); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100, 101); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, nullptr, &budget_off, &budget_val); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, "foo", &budget_off, &budget_val); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget( - ctx_, partitioner, "b", &budget); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, "b", &budget_off, &budget_val); - CHECK(rc == TILEDB_OK); - CHECK(budget_off == 100); - CHECK(budget_val == 101); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, TILEDB_COORDS, 100, 101); - CHECK(rc == TILEDB_ERR); - rc = tiledb_subarray_partitioner_get_result_budget_var( - ctx_, partitioner, TILEDB_COORDS, &budget_off, &budget_val); - CHECK(rc == TILEDB_ERR); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, empty array", - "[capi], [subarray-partitioner], [subarray-partitioner-empty-array]") { - std::string array_name = "subarray_partitioner_empty_array"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check current (should be empty) - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - tiledb_subarray_free(&partition); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 100); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, whole subarray fits", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-whole-subarray-fits]") { - // Create array - std::string array_name = "subarray_partitioner_whole_subarray_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // --- WITHOUT BUDGET --- - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 100); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // --- WITH BUDGET --- - - // Clean up - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - - // Create partitioner - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 100); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, split once", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {3, 11}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 7); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 8); - CHECK(r[1] == 11); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, unsplittable at once", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-unsplittable-at-once]") { - // Create array - std::string array_name = "subarray_partitioner_unsplittable_at_once"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, split multiple", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 18}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 6); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 11); - CHECK(r[1] == 18); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, unsplittable after multiple", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-unsplittable-after-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_unsplittable_after_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 18}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, unsplittable but ok after budget " - "reset", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-unsplittable-then-ok]") { - // Create array - std::string array_name = "subarray_partitioner_unsplittable_then_ok"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 18}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Set budget again - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100, 100); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, float, split multiple", - "[capi], [subarray-partitioner],[subarray-partitioner-float] " - "[subarray-partitioner-float-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_float_split_multiple"; - remove_array(array_name); - float domain[] = {1.0f, 100.0f}; - create_sparse_array_1d_float(array_name, domain); - std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - float s[] = {2.0f, 18.0f}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const float* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2.0f); - CHECK(r[1] == 4.0f); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - auto max = std::numeric_limits::max(); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == std::nextafter(4.0f, max)); - CHECK(r[1] == 6.0f); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == std::nextafter(6.0f, max)); - CHECK(r[1] == 10.0f); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == std::nextafter(10.0f, max)); - CHECK(r[1] == 18.0f); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, float, unsplittable after multiple", - "[capi], [subarray-partitioner],[subarray-partitioner-float] " - "[subarray-partitioner-float-unsplittable-after-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_unsplittable_after_multiple"; - remove_array(array_name); - float domain[] = {1, 100}; - create_sparse_array_1d_float(array_name, domain); - std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - float s[] = {2.0f, 18.0f}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 0, 0); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, float, whole subarray fits", - "[capi], [subarray-partitioner][subarray-partitioner-float] " - "[subarray-partitioner-float-whole-subarray-fits]") { - // Create array - std::string array_name = "subarray_partitioner_float_whole_subarray_fits"; - remove_array(array_name); - float domain[] = {1.0f, 100.0f}; - create_sparse_array_1d_float(array_name, domain); - std::vector coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const float* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1.0f); - CHECK(r[1] == 100.0f); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, whole subarray fits", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-whole-subarray-fits]") { - // Create array - std::string array_name = "subarray_partitioner_2d_whole_subarray_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row-major, split once", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-row-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 2 * 2 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 2); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col-major, split once", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-col-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 4 * 2 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row-major, split multiple", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-row-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {3, 4, 1, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 2 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 3); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 6); - CHECK(r2[1] == 8); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 9); - CHECK(r2[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 6); - CHECK(r2[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col-major, split multiple", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-col-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {1, 10, 1, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 2 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 3); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 5); - CHECK(r2[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 6); - CHECK(r2[1] == 7); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 8); - CHECK(r2[1] == 8); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 9); - CHECK(r2[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row-major, unsplittable", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-row-unsplittable]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {1, 10, 2, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 0); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col-major, unsplittable", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-col-unsplittable]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {1, 10, 1, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 0); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, multiple ranges, fits", - "[capi], [subarray-partitioner][subarray-partitioner-1d] " - "[subarray-partitioner-1d-multiple][subarray-partitioner-1d-multiple-" - "fit]") { - // Create array - std::string array_name = "subarray_partitioner_1d_multiple_fit"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {5, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {25, 27}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {33, 50}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 25); - CHECK(r[1] == 27); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 33); - CHECK(r[1] == 50); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, multiple ranges, split once", - "[capi], [subarray-partitioner][subarray-partitioner-1d] " - "[subarray-partitioner-1d-multiple]" - "[subarray-partitioner-1d-multiple-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_1d_multiple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {5, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {25, 27}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {33, 50}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 4 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 10); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 25); - CHECK(r[1] == 27); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 33); - CHECK(r[1] == 50); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, multiple ranges, split multiple", - "[capi], [subarray-partitioner][subarray-partitioner-1d] " - "[subarray-partitioner-1d-multiple]" - "[subarray-partitioner-1d-multiple-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_1d_multiple_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {5, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {25, 27}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {33, 50}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 25); - CHECK(r[1] == 27); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 33); - CHECK(r[1] == 50); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, multiple ranges, split mixed", - "[capi], [subarray-partitioner][subarray-partitioner-1d] " - "[subarray-partitioner-1d-multiple]" - "[subarray-partitioner-1d-multiple-split-mixed]") { - // Create array - std::string array_name = "subarray_partitioner_1d_multiple_split_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {5, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {25, 27}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {33, 40}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int) - 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 7); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 8); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 25); - CHECK(r[1] == 26); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 27); - CHECK(r[1] == 27); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 33); - CHECK(r[1] == 36); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 37); - CHECK(r[1] == 40); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, multiple ranges, unsplittable", - "[capi], [subarray-partitioner][subarray-partitioner-1d] " - "[subarray-partitioner-1d-multiple]" - "[subarray-partitioner-1d-multiple-unsplittable]") { - // Create array - std::string array_name = "subarray_partitioner_1d_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40}; - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {5, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {25, 27}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {33, 40}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row, multiple ranges, fits", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-row]" - "[subarray-partitioner-2d-multiple-fits]" - "[subarray-partitioner-2d-multiple-fits-row]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_multiple_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row, multiple ranges, split once", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-row]" - "[subarray-partitioner-2d-multiple-split-once]" - "[subarray-partitioner-2d-multiple-split-once-row]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_mulitple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {6, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 4 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row, multiple ranges, calibrate", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-row]" - "[subarray-partitioner-2d-multiple-calibrate]" - "[subarray-partitioner-2d-multiple-calibrate-row]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_multiple_calibrate"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {6, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 5 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row, multiple ranges, unsplittable", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-row]" - "[subarray-partitioner-2d-multiple-unsplittable]" - "[subarray-partitioner-2d-multiple-unsplittable-row]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {6, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, row, multiple ranges, mixed", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-row]" - "[subarray-partitioner-2d-multiple-mixed]" - "[subarray-partitioner-2d-multiple-mixed-row]") { - // Create array - std::string array_name = "subarray_partitioner_2d_row_multiple_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_ROW_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {6, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 2 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Increase budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 1000000); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col, multiple ranges, fits", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-col]" - "[subarray-partitioner-2d-multiple-fits]" - "[subarray-partitioner-2d-multiple-fits-col]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_multiple_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {7, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col, multiple ranges, split once", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-col]" - "[subarray-partitioner-2d-multiple-split-once]" - "[subarray-partitioner-2d-multiple-split-once-col]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_mulitple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {7, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 4 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col, multiple ranges, unsplittable", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-col]" - "[subarray-partitioner-2d-multiple-unsplittable]" - "[subarray-partitioner-2d-multiple-unsplittable-col]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {7, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col, multiple ranges, calibrate", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-col]" - "[subarray-partitioner-2d-multiple-calibrate]" - "[subarray-partitioner-2d-multiple-calibrate-col]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_multiple_calibrate"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {7, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 2D, col, multiple ranges, mixed", - "[capi], [subarray-partitioner][subarray-partitioner-2d] " - "[subarray-partitioner-2d-multiple]" - "[subarray-partitioner-2d-multiple-col]" - "[subarray-partitioner-2d-multiple-mixed]" - "[subarray-partitioner-2d-multiple-mixed-col]") { - // Create array - std::string array_name = "subarray_partitioner_2d_col_multiple_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 10, 1, 10}; - create_sparse_array_2d(array_name, domain, TILEDB_COL_MAJOR); - std::vector coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {7, 9}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 1 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Increase budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 1000000); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 5); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 9); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, 1D, memory budget", - "[capi], [subarray-partitioner], " - "[subarray-partitioner-1d-memory-budget]") { - // Create array - std::string array_name = "subarray_partitioner_1d_memory_budget"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - create_sparse_array_1d(array_name, domain); - std::vector coords = {2, 4, 5, 10, 12, 18}; - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - write_sparse_array(array_name, coords, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_UNORDERED, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, TILEDB_COORDS, 100 * sizeof(uint64_t)); - CHECK(rc == TILEDB_OK); - - // Get memory budget - uint64_t memory_budget, memory_budget_var; - rc = tiledb_subarray_partitioner_get_memory_budget( - ctx_, partitioner, &memory_budget, &memory_budget_var); - CHECK(rc == TILEDB_OK); - CHECK(memory_budget == 5368709120); - CHECK(memory_budget_var == 10737418240); - - // Set memory budget - rc = tiledb_subarray_partitioner_set_memory_budget(ctx_, partitioner, 16, 16); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_get_memory_budget( - ctx_, partitioner, &memory_budget, &memory_budget_var); - CHECK(rc == TILEDB_OK); - CHECK(memory_budget == 16); - CHECK(memory_budget_var == 16); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 4); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, empty array", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-empty-array]") { - std::string array_name = "subarray_partitioner_dense_empty_array"; - remove_array(array_name); - uint64_t domain[] = {1, 100}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check current (should be empty) - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - tiledb_subarray_free(&partition); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 100); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, whole subarray fits", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-whole-subarray-fits]") { - // Create array - std::string array_name = "subarray_partitioner_dense_whole_subarray_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // --- WITHOUT BUDGET --- - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 6); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // --- WITH BUDGET --- - - // Clean up - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - - // Create partitioner - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 6); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, split once", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_dense_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 5}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, unsplittable at once", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-unsplittable-at-once]") { - // Create array - std::string array_name = "subarray_partitioner_dense_unsplittable_at_once"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, split multiple", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_dense_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {1, 6}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 5); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next current and check - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 6); - CHECK(r[1] == 6); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, unsplittable after multiple", - "[capi][subarray-partitioner][subarray-partitioner-dense]" - "[subarray-partitioner-dense-unsplittable-after-multiple]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_unsplittable_after_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 6}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, unsplittable but ok after " - "budget reset", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense]" - "[subarray-partitioner-dense-unsplittable-then-ok]") { - // Create array - std::string array_name = "subarray_partitioner_dense_unsplittable_then_ok"; - remove_array(array_name); - uint64_t domain[] = {1, 6}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6}; - std::vector subdomain = {1, 6}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Add subarray range - uint64_t s[] = {2, 6}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 1, 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Set budget again - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100, 100); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, whole subarray fits", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d]" - "[subarray-partitioner-dense-2d-whole-subarray-fits]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_whole_subarray_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_set_result_budget_var( - ctx_, partitioner, "b", 100000, 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 4); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row-major, split once", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d]" - "[subarray-partitioner-dense-2d-row-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_row_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 8 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 2); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col-major, split once", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-col-split-once]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_col_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 8 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 4); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 1); - CHECK(r2[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Get next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 1); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 3); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row-major, split multiple", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-row-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_row_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {2, 4, 2, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 2); - CHECK(r1[1] == 2); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 2); - CHECK(r1[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 3); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col-major, split multiple", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-col-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_col_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {2, 4, 2, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r1; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 2); - CHECK(r1[1] == 3); - const uint64_t* r2; - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 2); - CHECK(r2[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 2); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 3); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 3); - CHECK(r2[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 2); - CHECK(r1[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r1); - CHECK(rc == TILEDB_OK); - CHECK(r1[0] == 4); - CHECK(r1[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r2); - CHECK(rc == TILEDB_OK); - CHECK(r2[0] == 4); - CHECK(r2[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row-major, unsplittable", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-row-unsplittable]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_row_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {1, 4, 1, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 0); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col-major, unsplittable", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-col-unsplittable]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_col_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t s[] = {1, 4, 1, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, s); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_add_range(ctx_, subarray, 1, &s[2]); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 0); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, multiple ranges, fits", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-1d] " - "[subarray-partitioner-dense-1d-multiple]" - "[subarray-partitioner-dense-1d-multiple-fit]") { - // Create array - std::string array_name = "subarray_partitioner_dense_1d_multiple_fit"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {5, 8}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {9, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 8); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 9); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, multiple ranges, split once", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-1d] " - "[subarray-partitioner-dense-1d-multiple]" - "[subarray-partitioner-dense-1d-multiple-split-multiple]") { - // Create array - std::string array_name = "subarray_partitioner_dense_1d_multiple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {5, 8}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {9, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 7 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 8); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 9); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, multiple ranges, split " - "multiple", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-1d] " - "[subarray-partitioner-dense-1d-multiple]" - "[subarray-partitioner-dense-1d-multiple-split-multiple]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_1d_multiple_split_multiple"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {5, 8}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {9, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 4 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 8); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 9); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, multiple ranges, split mixed", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-1d] " - "[subarray-partitioner-dense-1d-multiple]" - "[subarray-partitioner-dense-1d-multiple-split-mixed]") { - // Create array - std::string array_name = "subarray_partitioner_dense_1d_multiple_split_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {5, 8}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {9, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 2 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 5); - CHECK(r[1] == 6); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 7); - CHECK(r[1] == 8); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 9); - CHECK(r[1] == 10); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, multiple ranges, " - "unsplittable", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-1d] " - "[subarray-partitioner-dense-1d-multiple]" - "[subarray-partitioner-dense-1d-multiple-unsplittable]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_1d_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r1[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r1); - CHECK(rc == TILEDB_OK); - uint64_t r2[] = {5, 8}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r2); - CHECK(rc == TILEDB_OK); - uint64_t r3[] = {9, 10}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r3); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row, multiple ranges, fits", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-row]" - "[subarray-partitioner-dense-2d-multiple-fits]" - "[subarray-partitioner-dense-2d-multiple-fits-row]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_row_multiple_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row, multiple ranges, split " - "once", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-row]" - "[subarray-partitioner-dense-2d-multiple-split-once]" - "[subarray-partitioner-dense-2d-multiple-split-once-row]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_row_mulitple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 9 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row, multiple ranges, " - "calibrate", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-row]" - "[subarray-partitioner-dense-2d-multiple-calibrate]" - "[subarray-partitioner-dense-2d-multiple-calibrate-row]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_row_multiple_calibrate"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 11 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row, multiple ranges, " - "unsplittable", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-row]" - "[subarray-partitioner-dense-2d-multiple-unsplittable]" - "[subarray-partitioner-dense-2d-multiple-unsplittable-row]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_row_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, row, multiple ranges, mixed", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-row]" - "[subarray-partitioner-dense-2d-multiple-mixed]" - "[subarray-partitioner-dense-2d-multiple-mixed-row]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_row_multiple_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_ROW_MAJOR; - tiledb_layout_t tile_order = TILEDB_ROW_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r13[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r13); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {2, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 3 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Increase budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 1000000); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col, multiple ranges, fits", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-col]" - "[subarray-partitioner-dense-2d-multiple-fits]" - "[subarray-partitioner-dense-2d-multiple-fits-col]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_col_multiple_fits"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100000); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 3); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 2, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col, multiple ranges, split " - "once", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-col]" - "[subarray-partitioner-dense-2d-multiple-split-once]" - "[subarray-partitioner-dense-2d-multiple-split-once-col]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_col_mulitple_split_once"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 12 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col, multiple ranges, " - "unsplittable", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-col]" - "[subarray-partitioner-dense-2d-multiple-unsplittable]" - "[subarray-partitioner-dense-2d-multiple-unsplittable-col]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_col_multiple_unsplittable"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget(ctx_, partitioner, "a", 1); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col, multiple ranges, " - "calibrate", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-col]" - "[subarray-partitioner-dense-2d-multiple-calibrate]" - "[subarray-partitioner-dense-2d-multiple-calibrate-col]") { - // Create array - std::string array_name = - "subarray_partitioner_dense_2d_col_multiple_calibrate"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 10 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 2D, col, multiple ranges, mixed", - "[capi][subarray-partitioner-dense][subarray-partitioner-dense-2d] " - "[subarray-partitioner-dense-2d-multiple]" - "[subarray-partitioner-dense-2d-multiple-col]" - "[subarray-partitioner-dense-2d-multiple-mixed]" - "[subarray-partitioner-dense-2d-multiple-mixed-col]") { - // Create array - std::string array_name = "subarray_partitioner_dense_2d_col_multiple_mixed"; - remove_array(array_name); - uint64_t domain[] = {1, 4, 1, 4}; - uint64_t tile_extent = 2; - tiledb_layout_t cell_order = TILEDB_COL_MAJOR; - tiledb_layout_t tile_order = TILEDB_COL_MAJOR; - create_dense_array_2d( - array_name, domain, tile_extent, cell_order, tile_order); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 17 * sizeof(int), - 20 * sizeof(int), - 21 * sizeof(int), - 23 * sizeof(int), - 24 * sizeof(int), - 25 * sizeof(int), - 27 * sizeof(int), - 28 * sizeof(int), - 29 * sizeof(int)}; - std::vector b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, - 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 10, - 10, 11, 12, 13, 13, 14, 15, 16, 16}; - std::vector subdomain = {1, 4, 1, 4}; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_COL_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - uint64_t r11[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r11); - CHECK(rc == TILEDB_OK); - uint64_t r12[] = {3, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 0, r12); - CHECK(rc == TILEDB_OK); - uint64_t r21[] = {1, 2}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r21); - CHECK(rc == TILEDB_OK); - uint64_t r22[] = {3, 3}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r22); - CHECK(rc == TILEDB_OK); - uint64_t r23[] = {4, 4}; - rc = tiledb_subarray_add_range(ctx_, subarray, 1, r23); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 4 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 1); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 2); - CHECK(r[1] == 2); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Increase budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 1000000); - CHECK(rc == TILEDB_OK); - - // Check next - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range_num(ctx_, partition, 1, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - rc = tiledb_subarray_get_range(ctx_, partition, 0, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 4); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 3); - CHECK(r[1] == 3); - rc = tiledb_subarray_get_range(ctx_, partition, 1, 1, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 4); - CHECK(r[1] == 4); - - // Check done again - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 1); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} - -TEST_CASE_METHOD( - SubarrayPartitionerFx, - "C API: Test subarray partitioner, dense, 1D, memory budget", - "[capi][subarray-partitioner-dense], " - "[subarray-partitioner-dense-1d-memory-budget]") { - // Create array - std::string array_name = "subarray_partitioner_dense_1d_memory_budget"; - remove_array(array_name); - uint64_t domain[] = {1, 10}; - uint64_t tile_extent = 2; - create_dense_array_1d(array_name, domain, tile_extent); - std::vector a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector b_off = {0, - sizeof(int), - 3 * sizeof(int), - 6 * sizeof(int), - 9 * sizeof(int), - 11 * sizeof(int), - 15 * sizeof(int), - 16 * sizeof(int), - 17 * sizeof(int), - 18 * sizeof(int)}; - std::vector b_val = { - 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10}; - std::vector subdomain; - write_dense_array(array_name, subdomain, a, b_off, b_val); - - // Open array - tiledb_array_t* array; - int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array); - CHECK(rc == TILEDB_OK); - rc = tiledb_array_open(ctx_, array, TILEDB_READ); - CHECK(rc == TILEDB_OK); - - // Create subarray - tiledb_subarray_t* subarray = nullptr; - rc = tiledb_subarray_alloc(ctx_, array, TILEDB_ROW_MAJOR, &subarray); - CHECK(rc == TILEDB_OK); - - // Create partitioner - tiledb_subarray_partitioner_t* partitioner; - rc = tiledb_subarray_partitioner_alloc(ctx_, subarray, &partitioner); - CHECK(rc == TILEDB_OK); - - // Set budget - rc = tiledb_subarray_partitioner_set_result_budget( - ctx_, partitioner, "a", 100 * sizeof(int)); - CHECK(rc == TILEDB_OK); - - // Get memory budget - uint64_t memory_budget, memory_budget_var; - rc = tiledb_subarray_partitioner_get_memory_budget( - ctx_, partitioner, &memory_budget, &memory_budget_var); - CHECK(rc == TILEDB_OK); - CHECK(memory_budget == 5368709120); - CHECK(memory_budget_var == 10737418240); - - // Set memory budget - rc = tiledb_subarray_partitioner_set_memory_budget(ctx_, partitioner, 8, 8); - CHECK(rc == TILEDB_OK); - rc = tiledb_subarray_partitioner_get_memory_budget( - ctx_, partitioner, &memory_budget, &memory_budget_var); - CHECK(rc == TILEDB_OK); - CHECK(memory_budget == 8); - CHECK(memory_budget_var == 8); - - // Check done - int done; - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Check next - int unsplittable; - rc = tiledb_subarray_partitioner_next(ctx_, partitioner, &unsplittable); - CHECK(rc == TILEDB_OK); - CHECK(unsplittable == 0); - - // Get current and check - tiledb_subarray_t* partition = nullptr; - rc = tiledb_subarray_partitioner_get_current(ctx_, partitioner, &partition); - CHECK(rc == TILEDB_OK); - uint64_t range_num; - rc = tiledb_subarray_get_range_num(ctx_, partition, 0, &range_num); - CHECK(rc == TILEDB_OK); - CHECK(range_num == 1); - const uint64_t* r; - rc = tiledb_subarray_get_range(ctx_, partition, 0, 0, (const void**)&r); - CHECK(rc == TILEDB_OK); - CHECK(r[0] == 1); - CHECK(r[1] == 2); - - // Check done - rc = tiledb_subarray_partitioner_done(ctx_, partitioner, &done); - CHECK(rc == TILEDB_OK); - CHECK(done == 0); - - // Clean-up - rc = tiledb_array_close(ctx_, array); - CHECK(rc == TILEDB_OK); - tiledb_array_free(&array); - CHECK(array == nullptr); - tiledb_subarray_free(&subarray); - CHECK(subarray == nullptr); - tiledb_subarray_free(&partition); - CHECK(partition == nullptr); - tiledb_subarray_partitioner_free(&partitioner); - CHECK(partitioner == nullptr); - - remove_array(array_name); -} diff --git a/test/src/unit-rtree.cc b/test/src/unit-rtree.cc index 9e83c97f2818..8929f9a342a4 100644 --- a/test/src/unit-rtree.cc +++ b/test/src/unit-rtree.cc @@ -6,7 +6,6 @@ * The MIT License * * @copyright Copyright (c) 2017-2019 TileDB, Inc. - * @copyright Copyright (c) 2016 MIT and Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/tiledb/sm/array_schema/domain.cc b/tiledb/sm/array_schema/domain.cc index ea71291601ba..255155fbff45 100644 --- a/tiledb/sm/array_schema/domain.cc +++ b/tiledb/sm/array_schema/domain.cc @@ -132,6 +132,18 @@ Layout Domain::cell_order() const { return cell_order_; } +template +T Domain::floor_to_tile(T value, unsigned dim_idx) const { + auto domain = (T*)domain_; + auto tile_extents = (T*)tile_extents_; + + if (tile_extents_ == nullptr) + return domain[2 * dim_idx]; + + uint64_t div = (value - domain[2 * dim_idx]) / tile_extents[dim_idx]; + return (T)div * tile_extents[dim_idx] + domain[2 * dim_idx]; +} + Layout Domain::tile_order() const { return tile_order_; } @@ -1061,6 +1073,10 @@ void Domain::compute_tile_offsets() { template void Domain::compute_tile_offsets() { + // // Non-applicable to real domains + // if(!std::is_integral()) + // return; + // Applicable only to non-NULL space tiles if (tile_extents_ == nullptr) return; @@ -1102,18 +1118,6 @@ std::string Domain::default_dimension_name(unsigned int i) const { return ss.str(); } -template -T Domain::floor_to_tile(T value, unsigned dim_idx) const { - auto domain = (T*)domain_; - auto tile_extents = (T*)tile_extents_; - - if (tile_extents_ == nullptr) - return domain[2 * dim_idx]; - - uint64_t div = (value - domain[2 * dim_idx]) / tile_extents[dim_idx]; - return (T)div * tile_extents[dim_idx] + domain[2 * dim_idx]; -} - template uint64_t Domain::get_cell_pos_col(const T* coords) const { // For easy reference @@ -1840,5 +1844,26 @@ template uint64_t Domain::get_cell_pos_row( template uint64_t Domain::get_cell_pos_row( const uint64_t* subarray, const uint64_t* coords) const; +template int8_t Domain::floor_to_tile( + int8_t value, unsigned dim_idx) const; +template uint8_t Domain::floor_to_tile( + uint8_t value, unsigned dim_idx) const; +template int16_t Domain::floor_to_tile( + int16_t value, unsigned dim_idx) const; +template uint16_t Domain::floor_to_tile( + uint16_t value, unsigned dim_idx) const; +template int32_t Domain::floor_to_tile( + int32_t value, unsigned dim_idx) const; +template uint32_t Domain::floor_to_tile( + uint32_t value, unsigned dim_idx) const; +template int64_t Domain::floor_to_tile( + int64_t value, unsigned dim_idx) const; +template uint64_t Domain::floor_to_tile( + uint64_t value, unsigned dim_idx) const; +template float Domain::floor_to_tile( + float value, unsigned dim_idx) const; +template double Domain::floor_to_tile( + double value, unsigned dim_idx) const; + } // namespace sm } // namespace tiledb diff --git a/tiledb/sm/array_schema/domain.h b/tiledb/sm/array_schema/domain.h index 256396c9033b..5318693d51fe 100644 --- a/tiledb/sm/array_schema/domain.h +++ b/tiledb/sm/array_schema/domain.h @@ -77,6 +77,20 @@ class Domain { /* API */ /* ********************************* */ + /** + * Floors the value such that it coincides with the largest start of a tile + * that is smaller than value, on a given dimension. If there are no tile + * extents, then the returned value is the start of the domain on the input + * dimension. + * + * @tparam T The domain type. + * @param value The value to be floored. + * @param dim_idx The targeted dimension. + * @return The floored value. + */ + template + T floor_to_tile(T value, unsigned dim_idx) const; + /** * Splits the input subarray in half, in a way that the input layout is * respected. This means that if the two resulting subarrays were to @@ -723,20 +737,6 @@ class Domain { /** Returns the default name constructed for the i-th dimension. */ std::string default_dimension_name(unsigned int i) const; - /** - * Floors the value such that it coincides with the largest start of a tile - * that is smaller than value, on a given dimension. If there are no tile - * extents, then the returned value is the start of the domain on the input - * dimension. - * - * @tparam T The domain type. - * @param value The value to be floored. - * @param dim_idx The targeted dimension. - * @return The floored value. - */ - template - T floor_to_tile(T value, unsigned dim_idx) const; - /** * Retrieves the next tile coordinates along the array tile order within a * given tile domain. Applicable only to **dense** arrays, and focusing on diff --git a/tiledb/sm/c_api/tiledb.cc b/tiledb/sm/c_api/tiledb.cc index 2d7bb95c0b80..7c10b0870ef7 100644 --- a/tiledb/sm/c_api/tiledb.cc +++ b/tiledb/sm/c_api/tiledb.cc @@ -34,6 +34,7 @@ #include "tiledb/sm/c_api/tiledb.h" #include "tiledb/sm/array/array.h" #include "tiledb/sm/array_schema/array_schema.h" +#include "tiledb/sm/c_api/tiledb_struct_def.h" #include "tiledb/sm/cpp_api/core_interface.h" #include "tiledb/sm/filesystem/vfs_file_handle.h" #include "tiledb/sm/filter/compression_filter.h" @@ -93,95 +94,6 @@ void tiledb_version(int32_t* major, int32_t* minor, int32_t* rev) { *rev = tiledb::sm::constants::library_version[2]; } -/* ********************************* */ -/* TILEDB TYPES */ -/* ********************************* */ - -struct tiledb_array_t { - tiledb::sm::Array* array_ = nullptr; -}; - -struct tiledb_buffer_t { - tiledb::sm::Datatype datatype_ = tiledb::sm::Datatype::UINT8; - tiledb::sm::Buffer* buffer_ = nullptr; -}; - -struct tiledb_config_t { - tiledb::sm::Config* config_ = nullptr; -}; - -struct tiledb_config_iter_t { - tiledb::sm::ConfigIter* config_iter_ = nullptr; -}; - -struct tiledb_ctx_t { - tiledb::sm::Context* ctx_ = nullptr; -}; - -struct tiledb_error_t { - std::string errmsg_; -}; - -struct tiledb_attribute_t { - tiledb::sm::Attribute* attr_ = nullptr; -}; - -struct tiledb_array_schema_t { - tiledb::sm::ArraySchema* array_schema_ = nullptr; -}; - -struct tiledb_dimension_t { - tiledb::sm::Dimension* dim_ = nullptr; -}; - -struct tiledb_domain_t { - tiledb::sm::Domain* domain_ = nullptr; -}; - -struct tiledb_filter_t { - tiledb::sm::Filter* filter_ = nullptr; -}; - -struct tiledb_filter_list_t { - tiledb::sm::FilterPipeline* pipeline_ = nullptr; -}; - -struct tiledb_query_t { - tiledb::sm::Query* query_ = nullptr; -}; - -struct tiledb_subarray_t { - tiledb::sm::Subarray* subarray_ = nullptr; -}; - -struct tiledb_subarray_partitioner_t { - tiledb::sm::SubarrayPartitioner* partitioner_ = nullptr; -}; - -struct tiledb_kv_schema_t { - tiledb::sm::ArraySchema* array_schema_ = nullptr; -}; - -struct tiledb_kv_t { - tiledb::sm::KV* kv_ = nullptr; -}; - -struct tiledb_kv_item_t { - tiledb::sm::KVItem* kv_item_ = nullptr; -}; - -struct tiledb_kv_iter_t { - tiledb::sm::KVIter* kv_iter_ = nullptr; -}; - -struct tiledb_vfs_t { - tiledb::sm::VFS* vfs_ = nullptr; -}; - -struct tiledb_vfs_fh_t { - tiledb::sm::VFSFileHandle* vfs_fh_ = nullptr; -}; - /* ********************************* */ /* AUXILIARY FUNCTIONS */ /* ********************************* */ @@ -363,18 +275,6 @@ inline int32_t sanity_check( return TILEDB_OK; } -inline int32_t sanity_check( - tiledb_ctx_t* ctx, const tiledb_subarray_partitioner_t* partitioner) { - if (partitioner == nullptr || partitioner->partitioner_ == nullptr) { - auto st = - tiledb::sm::Status::Error("Invalid TileDB subarray partitioner object"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_ERR; - } - return TILEDB_OK; -} - inline int32_t sanity_check( tiledb_ctx_t* ctx, const tiledb_kv_schema_t* kv_schema) { if (kv_schema == nullptr || kv_schema->array_schema_ == nullptr) { @@ -2873,6 +2773,7 @@ int32_t tiledb_subarray_alloc( return TILEDB_ERR; } + // TODO: Revisit these checks // Layout checks if (layout == TILEDB_GLOBAL_ORDER) { auto st = tiledb::sm::Status::Error( @@ -3051,245 +2952,6 @@ int32_t tiledb_subarray_get_est_result_size_var( return TILEDB_OK; } -/* ****************************** */ -/* SUBARRAY PARTITIONER */ -/* ****************************** */ - -int32_t tiledb_subarray_partitioner_alloc( - tiledb_ctx_t* ctx, - const tiledb_subarray_t* subarray, - tiledb_subarray_partitioner_t** partitioner) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, subarray) == TILEDB_ERR) { - *partitioner = nullptr; - return TILEDB_ERR; - } - - // Check query type - tiledb::sm::QueryType query_type; - if (SAVE_ERROR_CATCH(ctx, subarray->subarray_->get_query_type(&query_type))) - return TILEDB_ERR; - if (query_type == tiledb::sm::QueryType::WRITE) { - auto st = tiledb::sm::Status::Error( - "Failed to create TileDB subarray partitioner object; Subarray cannot " - "belong " - "to array opened for writes"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_ERR; - } - - // Create subarray partitioner struct - *partitioner = new (std::nothrow) tiledb_subarray_partitioner_t; - if (*partitioner == nullptr) { - auto st = tiledb::sm::Status::Error( - "Failed to create TileDB subarray partitioner object; Memory " - "allocation error"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_OOM; - } - - // Allocate a subarray partitioner object - (*partitioner)->partitioner_ = new (std::nothrow) - tiledb::sm::SubarrayPartitioner(*(subarray->subarray_)); - if ((*partitioner)->partitioner_ == nullptr) { - delete *partitioner; - *partitioner = nullptr; - tiledb::sm::Status st = tiledb::sm::Status::Error( - "Failed to create TileDB subarray partitioner object; Memory " - "allocation " - "error"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_OOM; - } - - // Success - return TILEDB_OK; -} - -void tiledb_subarray_partitioner_free( - tiledb_subarray_partitioner_t** partitioner) { - if (partitioner != nullptr && *partitioner != nullptr) { - delete (*partitioner)->partitioner_; - delete *partitioner; - *partitioner = nullptr; - } -} - -int32_t tiledb_subarray_partitioner_get_result_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t* budget) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, partitioner->partitioner_->get_result_budget(attr_name, budget))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_get_result_budget_var( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t* budget_off, - uint64_t* budget_val) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, - partitioner->partitioner_->get_result_budget( - attr_name, budget_off, budget_val))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_get_memory_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - uint64_t* budget, - uint64_t* budget_var) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, - partitioner->partitioner_->get_memory_budget(budget, budget_var))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_set_result_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t budget) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, partitioner->partitioner_->set_result_budget(attr_name, budget))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_set_result_budget_var( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t budget_off, - uint64_t budget_val) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, - partitioner->partitioner_->set_result_budget( - attr_name, budget_off, budget_val))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_set_memory_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - uint64_t budget, - uint64_t budget_var) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - if (SAVE_ERROR_CATCH( - ctx, - partitioner->partitioner_->set_memory_budget(budget, budget_var))) - return TILEDB_ERR; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_get_current( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - tiledb_subarray_t** partition) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - // Get current partition from partitioner - auto current = partitioner->partitioner_->current(); - - // Create subarray struct - *partition = new (std::nothrow) tiledb_subarray_t; - if (*partition == nullptr) { - auto st = tiledb::sm::Status::Error( - "Failed to get current partition; Memory allocation error when " - "creating subarray struct object"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_OOM; - } - - // Allocate a subarray object - (*partition)->subarray_ = new (std::nothrow) tiledb::sm::Subarray(current); - if ((*partition)->subarray_ == nullptr) { - delete *partition; - *partition = nullptr; - tiledb::sm::Status st = tiledb::sm::Status::Error( - "Failed to get current partition; Memory allocation error when " - "creating subarray object"); - LOG_STATUS(st); - save_error(ctx, st); - return TILEDB_OOM; - } - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_next( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - int* unsplittable) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - bool ret; - if (SAVE_ERROR_CATCH(ctx, partitioner->partitioner_->next(&ret))) - return TILEDB_ERR; - - *unsplittable = (int)ret; - - return TILEDB_OK; -} - -int32_t tiledb_subarray_partitioner_done( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - int* done) { - if (sanity_check(ctx) == TILEDB_ERR || - sanity_check(ctx, partitioner) == TILEDB_ERR) - return TILEDB_ERR; - - *done = (int)partitioner->partitioner_->done(); - - return TILEDB_OK; -} - /* ****************************** */ /* OBJECT MANAGEMENT */ /* ****************************** */ diff --git a/tiledb/sm/c_api/tiledb.h b/tiledb/sm/c_api/tiledb.h index 8ab638f53ff2..cdcb0c43e32c 100644 --- a/tiledb/sm/c_api/tiledb.h +++ b/tiledb/sm/c_api/tiledb.h @@ -262,9 +262,6 @@ typedef struct tiledb_query_t tiledb_query_t; /** A subarray object. */ typedef struct tiledb_subarray_t tiledb_subarray_t; -/** A subarray partitioner object. */ -typedef struct tiledb_subarray_partitioner_t tiledb_subarray_partitioner_t; - /** A key-value store schema. */ typedef struct tiledb_kv_schema_t tiledb_kv_schema_t; @@ -3575,237 +3572,6 @@ TILEDB_EXPORT int32_t tiledb_subarray_get_est_result_size_var( uint64_t* size_off, uint64_t* size_val); -/* ********************************* */ -/* SUBARRAY PARTITIONER */ -/* ********************************* */ - -/** - * Creates a subarray partitioner object for a subarray. - * - * **Example:** - * - * @code{.c} - * tiledb_array_t* array; - * tiledb_array_alloc(ctx, "file:///my_array", &array); - * tiledb_array_open(ctx, array, TILEDB_READ); - * tiledb_subarray_t* subarray; - * tiledb_subarray_alloc(ctx, array, TILEDB_UNORDERED, &subarray); - * tiledb_subarray_partitioner_t* partitioner; - * tiledb_subarray_partitioner_alloc(ctx, subarray, &partitioner); - * @endcode - * - * @param ctx The TileDB context. - * @param subarray The input subarray. - * @param partitioner The subarray partitioner to be created. - * @return `TILEDB_OK` for success and `TILEDB_OOM` or `TILEDB_ERR` for error. - * - * @note A subarray partitioner can only be created for subarrays - * of arrays opened in READ mode. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_alloc( - tiledb_ctx_t* ctx, - const tiledb_subarray_t* subarray, - tiledb_subarray_partitioner_t** partitioner); - -/** - * Deletes a subarray partitioner object. - * - * @param partitioner The subarray partitioner object to be deleted. - */ -TILEDB_EXPORT void tiledb_subarray_partitioner_free( - tiledb_subarray_partitioner_t** partitioner); - -/** - * Gets the result size budget set for a given fixed-sized attribute. - * - * **Example:** - * - * @code{.c} - * uint64_t budget; - * tiledb_subarray_partitioner_get_result_budget(ctx, partitioner, "a", - * &budget); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param attr_name The name of the attribute to set the budget for. - * @param budget The budget (in bytes) to be retrieved for the input attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_get_result_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t* budget); - -/** - * Gets the result size budget set for a given var-sized attribute. - * - * **Example:** - * - * @code{.c} - * uint64_t budget_off, budget_val; - * tiledb_subarray_partitioner_get_result_budget_var( - * ctx, partitioner, "a", &budget_off, &budget_val); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param attr_name The name of the attribute to set the budget for. - * @param budget_off The result size budget (in bytes) for the offsets to - * be retrieved for the input attribute. - * @param budget_val The result size budget (in bytes) for the values to - * be retrieved for the input attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_get_result_budget_var( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t* budget_off, - uint64_t* budget_val); - -/** - * Gets the memory budget (in bytes) that dictates the maximum amount - * of bytes to be read and decompressed for the attributes during - * reads. - * - * **Example:** - * - * @code{.c} - * uint64_t budget, budget_var; - * tiledb_subarray_partitioner_get_memory_budget( - * ctx, partitioner, &budget, &budget_var); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The partitioner. - * @param budget The memory budget for a fixed-sized attribute or the - * offsets of a var-sized attribute. - * @param budget_var The memory budget for a var-sized attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_get_memory_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - uint64_t* budget, - uint64_t* budget_var); - -/** - * Sets the result budget (in bytes) for a given fixed-sized attribute. - * - * **Example:** - * - * @code{.c} - * tiledb_subarray_partitioner_set_result_budget( - * ctx, partitioner, "a", 10000000); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The partitioner. - * @param attr_name The name of the attribute to set the budget for. - * @param budget The result size budget (in bytes) for this attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_set_result_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t budget); - -/** - * Sets the result budget (in bytes) for for a given var-sized attribute. - * - * **Example:** - * - * @code{.c} - * tiledb_subarray_partitioner_set_result_budget_var( - * ctx, partitioner, "a", 10000000, 10000000); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param attr_name The name of the attribute to set the budget for. - * @param budget_off The result size budget (in bytes) for the - * offsets of this attribute. - * @param budget_val The result size budget (in bytes) for the - * values of this attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_set_result_budget_var( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - const char* attr_name, - uint64_t budget_off, - uint64_t budget_val); - -/** - * Sets the memory budget (in bytes) that dictates the maximum amount - * of bytes to be read and decompressed for the attributes during - * reads. - * - * **Example:** - * - * @code{.c} - * tiledb_subarray_partitioner_set_memory_budget( - * ctx, partitioner, 10000000, 20000000); - * @endcode - * - * @param ctx The TileDB context. - * @param partitioner The partitioner. - * @param budget The memory budget for a fixed-sized attribute or the - * offsets of a var-sized attribute. - * @param budget_var The memory budget for a var-sized attribute. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_set_memory_budget( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - uint64_t budget, - uint64_t budget_var); - -/** - * Retrieves the current partition. - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param partition The partition to be retrieved. - * @return `TILEDB_OK` for success and `TILEDB_OOM` or `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_get_current( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - tiledb_subarray_t** partition); - -/** - * It advances the partitioner to the next partition. If the remaining - * subarray cannot be split further to produce the next partition, - * ``unsplittable`` is set to ``true``. - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param unsplittable Set to ``true`` if the remaining subarray cannot - * be split to produce the next partition. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_next( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - int32_t* unsplittable); - -/** - * Checks if the partitioner is done producing partitions. - * - * @param ctx The TileDB context. - * @param partitioner The subarray partitioner. - * @param done Sets it to ``true`` if the partitioner is done. - * @return `TILEDB_OK` for success and `TILEDB_ERR` for error. - */ -TILEDB_EXPORT int32_t tiledb_subarray_partitioner_done( - tiledb_ctx_t* ctx, - const tiledb_subarray_partitioner_t* partitioner, - int32_t* done); - /* ********************************* */ /* OBJECT MANAGEMENT */ /* ********************************* */ diff --git a/tiledb/sm/c_api/tiledb_struct_def.h b/tiledb/sm/c_api/tiledb_struct_def.h new file mode 100644 index 000000000000..8832d4784901 --- /dev/null +++ b/tiledb/sm/c_api/tiledb_struct_def.h @@ -0,0 +1,133 @@ +/** + * @file tiledb_struct_def.h + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2017-2018 TileDB, Inc. + * @copyright Copyright (c) 2016 MIT and Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * This file contains the TileDB C API struct object definitions. + */ + +#ifndef TILEDB_C_API_STRUCT_DEF_H +#define TILEDB_C_API_STRUCT_DEF_H + +#include "tiledb/sm/array/array.h" +#include "tiledb/sm/array_schema/array_schema.h" +#include "tiledb/sm/filesystem/vfs_file_handle.h" +#include "tiledb/sm/filter/compression_filter.h" +#include "tiledb/sm/filter/filter_pipeline.h" +#include "tiledb/sm/kv/kv.h" +#include "tiledb/sm/kv/kv_item.h" +#include "tiledb/sm/kv/kv_iter.h" +#include "tiledb/sm/query/query.h" +#include "tiledb/sm/storage_manager/config.h" +#include "tiledb/sm/storage_manager/config_iter.h" +#include "tiledb/sm/storage_manager/context.h" +#include "tiledb/sm/subarray/subarray.h" +#include "tiledb/sm/subarray/subarray_partitioner.h" + +struct tiledb_array_t { + tiledb::sm::Array* array_ = nullptr; +}; + +struct tiledb_buffer_t { + tiledb::sm::Datatype datatype_ = tiledb::sm::Datatype::UINT8; + tiledb::sm::Buffer* buffer_ = nullptr; +}; + +struct tiledb_config_t { + tiledb::sm::Config* config_ = nullptr; +}; + +struct tiledb_config_iter_t { + tiledb::sm::ConfigIter* config_iter_ = nullptr; +}; + +struct tiledb_ctx_t { + tiledb::sm::Context* ctx_ = nullptr; +}; + +struct tiledb_error_t { + std::string errmsg_; +}; + +struct tiledb_attribute_t { + tiledb::sm::Attribute* attr_ = nullptr; +}; + +struct tiledb_array_schema_t { + tiledb::sm::ArraySchema* array_schema_ = nullptr; +}; + +struct tiledb_dimension_t { + tiledb::sm::Dimension* dim_ = nullptr; +}; + +struct tiledb_domain_t { + tiledb::sm::Domain* domain_ = nullptr; +}; + +struct tiledb_filter_t { + tiledb::sm::Filter* filter_ = nullptr; +}; + +struct tiledb_filter_list_t { + tiledb::sm::FilterPipeline* pipeline_ = nullptr; +}; + +struct tiledb_query_t { + tiledb::sm::Query* query_ = nullptr; +}; + +struct tiledb_subarray_t { + tiledb::sm::Subarray* subarray_ = nullptr; +}; + +struct tiledb_kv_schema_t { + tiledb::sm::ArraySchema* array_schema_ = nullptr; +}; + +struct tiledb_kv_t { + tiledb::sm::KV* kv_ = nullptr; +}; + +struct tiledb_kv_item_t { + tiledb::sm::KVItem* kv_item_ = nullptr; +}; + +struct tiledb_kv_iter_t { + tiledb::sm::KVIter* kv_iter_ = nullptr; +}; + +struct tiledb_vfs_t { + tiledb::sm::VFS* vfs_ = nullptr; +}; + +struct tiledb_vfs_fh_t { + tiledb::sm::VFSFileHandle* vfs_fh_ = nullptr; +}; + +#endif \ No newline at end of file diff --git a/tiledb/sm/query/dense_cell_range_iter.h b/tiledb/sm/query/dense_cell_range_iter.h index 4295aed5953d..046da5479162 100644 --- a/tiledb/sm/query/dense_cell_range_iter.h +++ b/tiledb/sm/query/dense_cell_range_iter.h @@ -61,7 +61,7 @@ class DenseCellRangeIter { * Constructor. * * @param domain The array domain. - * @param subarray The subarray the iterator will focuse on. + * @param subarray The subarray the iterator will focus on. * @param layout The layout in which the cell ranges will be iterated on. */ DenseCellRangeIter( diff --git a/tiledb/sm/subarray/subarray.cc b/tiledb/sm/subarray/subarray.cc index fe37f21a5ce0..1d2849ce440f 100644 --- a/tiledb/sm/subarray/subarray.cc +++ b/tiledb/sm/subarray/subarray.cc @@ -467,7 +467,11 @@ std::vector Subarray::get_range_coords(uint64_t range_idx) const { } std::reverse(ret.begin(), ret.end()); } else { - assert(false); + // Global order - single range + assert(layout == Layout::GLOBAL_ORDER); + assert(range_num() == 1); + for (unsigned i = 0; i < dim_num; ++i) + ret.push_back(0); } return ret; @@ -515,7 +519,10 @@ std::vector Subarray::range(uint64_t range_idx) const { } std::reverse(ret.begin(), ret.end()); } else { - assert(false); + assert(layout == Layout::GLOBAL_ORDER); + assert(range_num() == 1); + for (unsigned i = 0; i < dim_num; ++i) + ret.push_back((T*)ranges_[i].get_range(0)); } return ret; @@ -598,7 +605,14 @@ void Subarray::compute_range_offsets() { } std::reverse(range_offsets_.begin(), range_offsets_.end()); } else { - assert(false); + // Global order - single range + assert(layout == Layout::GLOBAL_ORDER); + assert(range_num() == 1); + range_offsets_.push_back(1); + if (dim_num > 1) { + for (unsigned int i = 1; i < dim_num; ++i) + range_offsets_.push_back(1); + } } } @@ -784,7 +798,7 @@ Status Subarray::compute_tile_overlap() { // Compute estimated tile overlap in parallel over fragments and ranges auto statuses = parallel_for_2d( - 0, fragment_num, 0, range_num, [&](unsigned i, unsigned j) { + 0, fragment_num, 0, range_num, [&](unsigned i, uint64_t j) { auto range = this->range(j); if (meta[i]->dense()) { // Dense fragment tile_overlap_[i][j] = get_tile_overlap(range, i); diff --git a/tiledb/sm/subarray/subarray_partitioner.cc b/tiledb/sm/subarray/subarray_partitioner.cc index fdd970617bdc..76fb349c0bcd 100644 --- a/tiledb/sm/subarray/subarray_partitioner.cc +++ b/tiledb/sm/subarray/subarray_partitioner.cc @@ -72,7 +72,8 @@ SubarrayPartitioner::SubarrayPartitioner(const SubarrayPartitioner& partitioner) swap(clone); } -SubarrayPartitioner::SubarrayPartitioner(SubarrayPartitioner&& partitioner) +SubarrayPartitioner::SubarrayPartitioner( + SubarrayPartitioner&& partitioner) noexcept : SubarrayPartitioner() { swap(partitioner); } @@ -86,7 +87,7 @@ SubarrayPartitioner& SubarrayPartitioner::operator=( } SubarrayPartitioner& SubarrayPartitioner::operator=( - SubarrayPartitioner&& partitioner) { + SubarrayPartitioner&& partitioner) noexcept { swap(partitioner); return *this; @@ -109,7 +110,7 @@ Status SubarrayPartitioner::get_result_budget( // Check attribute name if (attr_name == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot get result budget; Invalid attribute")); + "Cannot get result budget; Attribute name cannot be null")); if (attr_name != constants::coords) { // Check attribute name @@ -133,7 +134,9 @@ Status SubarrayPartitioner::get_result_budget( auto b_it = budget_.find(attr_name); if (b_it == budget_.end()) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot get result budget; Budget not set for the input attribute")); + std::string( + "Cannot get result budget; Budget not set for attribute '") + + attr_name + "'")); // Get budget *budget = b_it->second.size_fixed_; @@ -146,7 +149,7 @@ Status SubarrayPartitioner::get_result_budget( // Check attribute name if (attr_name == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot get result budget; Invalid attribute")); + "Cannot get result budget; Attribute name cannot be null")); if (attr_name == constants::coords) return LOG_STATUS(Status::SubarrayPartitionerError( @@ -172,7 +175,9 @@ Status SubarrayPartitioner::get_result_budget( auto b_it = budget_.find(attr_name); if (b_it == budget_.end()) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot get result budget; Budget not set for the input attribute")); + std::string( + "Cannot get result budget; Budget not set for attribute '") + + attr_name + "'")); // Get budget *budget_off = b_it->second.size_fixed_; @@ -239,7 +244,10 @@ Status SubarrayPartitioner::next(bool* unsplittable) { RETURN_NOT_OK(compute_current_start_end(&interval_found)); // Single-range partition that must be split - if (!interval_found && subarray_.layout() == Layout::UNORDERED) + // Note: this applies only to UNORDERED and GLOBAL_ORDER layouts, + // since otherwise we may have to calibrate the range start and end + if (!interval_found && (subarray_.layout() == Layout::UNORDERED || + subarray_.layout() == Layout::GLOBAL_ORDER)) return next_from_single_range(unsplittable); // An interval of whole ranges that may need calibration @@ -264,14 +272,15 @@ Status SubarrayPartitioner::set_result_budget( // Check attribute name if (attr_name == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot set result budget; Invalid attribute")); + "Cannot set result budget; Attribute name cannot be null")); if (attr_name != constants::coords) { // Check attribute auto attr = subarray_.array()->array_schema()->attribute(attr_name); if (attr == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot set result budget; Invalid attribute")); + std::string("Cannot set result budget; Invalid attribute '") + + attr_name + "'")); // Check if the attribute is fixed-sized if (attr->var_size()) @@ -289,7 +298,7 @@ Status SubarrayPartitioner::set_result_budget( // Check attribute name if (attr_name == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot set result budget; Invalid attribute")); + "Cannot set result budget; Attribute name cannot be null")); if (attr_name == constants::coords) return LOG_STATUS(Status::SubarrayPartitionerError( @@ -299,7 +308,8 @@ Status SubarrayPartitioner::set_result_budget( auto attr = subarray_.array()->array_schema()->attribute(attr_name); if (attr == nullptr) return LOG_STATUS(Status::SubarrayPartitionerError( - "Cannot set result budget; Invalid attribute")); + std::string("Cannot set result budget; Invalid attribute '") + + attr_name + "'")); // Check if the attribute is var-sized if (!attr->var_size()) @@ -357,12 +367,18 @@ Status SubarrayPartitioner::split_current(bool* unsplittable) { /* ****************************** */ void SubarrayPartitioner::calibrate_current_start_end(bool* must_split_slab) { - auto start_coords = subarray_.get_range_coords(current_.start_); - auto end_coords = subarray_.get_range_coords(current_.end_); - // Initialize (may be reset below) *must_split_slab = false; + // Special case of single range and global layout + if (subarray_.layout() == Layout::GLOBAL_ORDER) { + assert(current_.start_ == current_.end_); + return; + } + + auto start_coords = subarray_.get_range_coords(current_.start_); + auto end_coords = subarray_.get_range_coords(current_.end_); + std::vector range_num; auto dim_num = subarray_.dim_num(); uint64_t num; @@ -475,11 +491,10 @@ Status SubarrayPartitioner::compute_current_start_end(bool* found) { attr_name, current_.end_, var_size, &est_size)); auto& cur_size = cur_sizes[attr_name]; auto& mem_size = mem_sizes[attr_name]; - cur_size.size_fixed_ += est_size.size_fixed_; - cur_size.size_var_ += est_size.size_var_; - mem_size.size_fixed_ += est_size.mem_size_fixed_; - mem_size.size_var_ += est_size.mem_size_var_; - + cur_size.size_fixed_ += (uint64_t)ceil(est_size.size_fixed_); + cur_size.size_var_ += (uint64_t)ceil(est_size.size_var_); + mem_size.size_fixed_ += (uint64_t)ceil(est_size.mem_size_fixed_); + mem_size.size_var_ += (uint64_t)ceil(est_size.mem_size_var_); if (cur_size.size_fixed_ > budget_it.second.size_fixed_ || cur_size.size_var_ > budget_it.second.size_var_ || mem_size.size_fixed_ > memory_budget_ || @@ -505,6 +520,58 @@ Status SubarrayPartitioner::compute_current_start_end(bool* found) { return Status::Ok(); } +template +void SubarrayPartitioner::compute_splitting_point_on_tiles( + const Subarray& range, + unsigned* splitting_dim, + T* splitting_point, + bool* unsplittable) { + assert(range.layout() == Layout::GLOBAL_ORDER); + *unsplittable = true; + + // For easy reference + auto array_schema = subarray_.array()->array_schema(); + auto domain = (const T*)array_schema->domain()->domain(); + auto tile_extents = (const T*)array_schema->domain()->tile_extents(); + auto dim_num = subarray_.array()->array_schema()->dim_num(); + auto layout = subarray_.array()->array_schema()->tile_order(); + const void* r_v; + *splitting_dim = UINT32_MAX; + + // Trivial case + if (tile_extents == nullptr) + return; + + std::vector dims; + if (layout == Layout::ROW_MAJOR) { + for (unsigned i = 0; i < dim_num; ++i) + dims.push_back(i); + } else { + for (unsigned i = 0; i < dim_num; ++i) + dims.push_back(dim_num - i - 1); + } + + // Compute splitting dimension and point + for (auto i : dims) { + range.get_range(i, 0, &r_v); + auto r = (T*)r_v; + auto tiles_apart = floor(((r[1] - domain[2 * i]) / tile_extents[i])) - + floor(((r[0] - domain[2 * i]) / tile_extents[i])); + if (tiles_apart != 0) { + *splitting_dim = i; + T mid = r[0] + MAX(1, floor(tiles_apart / 2)) * tile_extents[i]; + T floored_mid = array_schema->domain()->floor_to_tile(mid, i); + if (std::numeric_limits::is_integer) + *splitting_point = floored_mid - 1; + else + *splitting_point = + std::nextafter(floored_mid, std::numeric_limits::lowest()); + *unsplittable = false; + break; + } + } +} + // TODO (sp): in the future this can be more sophisticated, taking into // TODO (sp): account MBRs (i.e., the distirbution of the data) as well template @@ -513,12 +580,25 @@ void SubarrayPartitioner::compute_splitting_point_single_range( unsigned* splitting_dim, T* splitting_point, bool* unsplittable) { + // Special case for global order + if (subarray_.layout() == Layout::GLOBAL_ORDER) { + compute_splitting_point_on_tiles( + range, splitting_dim, splitting_point, unsplittable); + + if (!*unsplittable) + return; // Splitting dim/point found + // Else `range` is contained within a tile. + // The rest of the function will find the splitting dim/point + } + // For easy reference - auto layout = subarray_.layout(); auto dim_num = subarray_.array()->array_schema()->dim_num(); auto cell_order = subarray_.array()->array_schema()->cell_order(); assert(!range.is_unary()); - layout = (layout == Layout::UNORDERED) ? cell_order : layout; + auto layout = subarray_.layout(); + layout = (layout == Layout::UNORDERED || layout == Layout::GLOBAL_ORDER) ? + cell_order : + layout; const void* r_v; *splitting_dim = UINT32_MAX; @@ -539,7 +619,9 @@ void SubarrayPartitioner::compute_splitting_point_single_range( *splitting_dim = i; *splitting_point = r[0] + (r[1] - r[0]) / 2; *unsplittable = !std::memcmp(splitting_point, &r[1], sizeof(T)); - break; + if (!*unsplittable) + break; // Splitting dim/point found + // Else continue to the next dimension } } diff --git a/tiledb/sm/subarray/subarray_partitioner.h b/tiledb/sm/subarray/subarray_partitioner.h index 18dc4fe25394..1cfc276aee83 100644 --- a/tiledb/sm/subarray/subarray_partitioner.h +++ b/tiledb/sm/subarray/subarray_partitioner.h @@ -73,7 +73,7 @@ class SubarrayPartitioner { SubarrayPartitioner(); /** Constructor. */ - SubarrayPartitioner(const Subarray& subarray); + explicit SubarrayPartitioner(const Subarray& subarray); /** Destructor. */ ~SubarrayPartitioner(); @@ -82,13 +82,13 @@ class SubarrayPartitioner { SubarrayPartitioner(const SubarrayPartitioner& partitioner); /** Move constructor. */ - SubarrayPartitioner(SubarrayPartitioner&& partitioner); + SubarrayPartitioner(SubarrayPartitioner&& partitioner) noexcept; /** Copy-assign operator. This performs a deep copy. */ SubarrayPartitioner& operator=(const SubarrayPartitioner& partitioner); /** Move-assign operator. */ - SubarrayPartitioner& operator=(SubarrayPartitioner&& partitioner); + SubarrayPartitioner& operator=(SubarrayPartitioner&& partitioner) noexcept; /* ********************************* */ /* API */ @@ -309,6 +309,19 @@ class SubarrayPartitioner { template Status compute_current_start_end(bool* found); + /** + * Applicable only when the `range` layout is GLOBAL_ORDER. + * Computes the splitting point and dimension for the input range. + * If `range` is whithin a single space tile, then `unsplittable` + * is set to `true`. + */ + template + void compute_splitting_point_on_tiles( + const Subarray& range, + unsigned* splitting_dim, + T* splitting_point, + bool* unsplittable); + /** * Computes the splitting point and dimension for the input range. * In case of real domains, if this function may not be able to find a