Skip to content

Commit

Permalink
More Subarray refactoring towards addressing #93
Browse files Browse the repository at this point in the history
  • Loading branch information
stavrospapadopoulos committed Feb 28, 2020
1 parent 3637c98 commit be9efbd
Show file tree
Hide file tree
Showing 22 changed files with 604 additions and 1,135 deletions.
15 changes: 8 additions & 7 deletions test/src/helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,15 @@ void check_subarray(

// Check ranges
uint64_t dim_range_num = 0;
const T* range;
const sm::Range* 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]);
subarray.get_range(i, j, &range);
auto r = (const T*)range->data();
CHECK(r[0] == ranges[i][2 * j]);
CHECK(r[1] == ranges[i][2 * j + 1]);
}
}
}
Expand Down Expand Up @@ -367,10 +368,10 @@ void create_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 (unsigned d = 0; d < dim_num; ++d) {
auto dim_range_num = ranges[d].size() / 2;
for (size_t j = 0; j < dim_range_num; ++j) {
ret.add_range(i, &ranges[i][2 * j]);
ret.add_range(d, sm::Range(&ranges[d][2 * j], 2 * sizeof(T)));
}
}

Expand Down
8 changes: 4 additions & 4 deletions test/src/unit-Subarray.cc
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,14 @@ TEST_CASE_METHOD(
std::vector<uint64_t> c_range_1_1 = {5, 5};
auto cropped_subarray =
subarray.crop_to_tile(&tile_coords[0], Layout::ROW_MAJOR);
const void* range = nullptr;
const Range* range = nullptr;
CHECK(cropped_subarray.range_num() == 2);
CHECK(cropped_subarray.get_range(0, 0, &range).ok());
CHECK(!memcmp(range, &c_range_0_0[0], 2 * sizeof(uint64_t)));
CHECK(!memcmp(range->data(), &c_range_0_0[0], 2 * sizeof(uint64_t)));
CHECK(cropped_subarray.get_range(1, 0, &range).ok());
CHECK(!memcmp(range, &c_range_1_0[0], 2 * sizeof(uint64_t)));
CHECK(!memcmp(range->data(), &c_range_1_0[0], 2 * sizeof(uint64_t)));
CHECK(cropped_subarray.get_range(1, 1, &range).ok());
CHECK(!memcmp(range, &c_range_1_1[0], 2 * sizeof(uint64_t)));
CHECK(!memcmp(range->data(), &c_range_1_1[0], 2 * sizeof(uint64_t)));

close_array(ctx_, array_);
}
56 changes: 0 additions & 56 deletions test/src/unit-capi-dense_array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4098,62 +4098,6 @@ TEST_CASE_METHOD(
remove_temp_dir(temp_dir);
}

TEST_CASE_METHOD(
DenseArrayFx,
"C API: Test dense array, set subarray in sparse writes should error",
"[capi], [dense], [dense-set-subarray-sparse]") {
SECTION("- No serialization") {
serialize_query_ = false;
}
SECTION("- Serialization") {
serialize_query_ = true;
}

std::string array_name =
FILE_URI_PREFIX + FILE_TEMP_DIR + "dense_set_subarray_sparse";
std::string temp_dir = FILE_URI_PREFIX + FILE_TEMP_DIR;
create_temp_dir(temp_dir);
create_dense_array(array_name);

// Create TileDB context
tiledb_ctx_t* ctx = nullptr;
REQUIRE(tiledb_ctx_alloc(nullptr, &ctx) == TILEDB_OK);

// 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 WRITE query
tiledb_query_t* query;
rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
CHECK(rc == TILEDB_OK);

uint64_t subarray[] = {1, 1, 1, 1};

// Set some subarray BEFORE setting the layout to UNORDERED
rc = tiledb_query_set_subarray(ctx, query, subarray);
CHECK(rc == TILEDB_OK);

// Set some subarray AFTER setting the layout to UNORDERED
rc = tiledb_query_set_layout(ctx, query, TILEDB_UNORDERED);
CHECK(rc == TILEDB_OK);
rc = tiledb_query_set_subarray(ctx, query, subarray);
CHECK(rc == TILEDB_ERR);

// Close array
CHECK(tiledb_array_close(ctx, array) == TILEDB_OK);

// Clean up
tiledb_query_free(&query);
tiledb_array_free(&array);
tiledb_ctx_free(&ctx);

remove_temp_dir(temp_dir);
}

TEST_CASE_METHOD(
DenseArrayFx,
"C API: Test dense array, check if coords exist in unordered writes",
Expand Down
1 change: 1 addition & 0 deletions test/src/unit-cppapi-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ TEST_CASE("C++ API: Encrypted array", "[cppapi][encryption]") {
Array array(ctx, array_name, TILEDB_WRITE, TILEDB_AES_256_GCM, key, key_len);
REQUIRE(Array::encryption_type(ctx, array_name) == TILEDB_AES_256_GCM);
array.close();

REQUIRE_THROWS_AS(array.open(TILEDB_WRITE), tiledb::TileDBError);
array.open(TILEDB_WRITE, TILEDB_AES_256_GCM, key, key_len);
REQUIRE(Array::encryption_type(ctx, array_name) == TILEDB_AES_256_GCM);
Expand Down
176 changes: 172 additions & 4 deletions tiledb/sm/array_schema/dimension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Dimension::Dimension(const std::string& name, Datatype type)
domain_ = nullptr;
tile_extent_ = nullptr;
set_ceil_to_tile_func();
set_check_range_func();
set_coincides_with_tiles_func();
set_compute_mbr_func();
set_crop_range_func();
set_domain_range_func();
Expand Down Expand Up @@ -208,6 +210,8 @@ Status Dimension::deserialize(ConstBuffer* buff, Datatype type) {
}

set_ceil_to_tile_func();
set_check_range_func();
set_coincides_with_tiles_func();
set_compute_mbr_func();
set_crop_range_func();
set_domain_range_func();
Expand Down Expand Up @@ -288,6 +292,64 @@ void Dimension::ceil_to_tile(
ceil_to_tile_func_(this, r, tile_num, v);
}

template <class T>
bool Dimension::check_range(
const Dimension* dim, const Range& range, std::string* err_msg) {
auto domain = (const T*)dim->domain();
auto r = (const T*)range.data();

// Check for NaN
if (!std::is_integral<T>::value && (std::isnan(r[0]) || std::isnan(r[1]))) {
*err_msg = "Cannot add range to dimension; Range contains NaN";
return false;
}

// Check range bounds
if (r[0] > r[1]) {
*err_msg =
"Cannot add range to dimension; Lower range "
"bound cannot be larger than the higher bound";
return false;
}

// Check out-of-bounds
if (r[0] < domain[0] || r[1] > domain[1]) {
std::stringstream ss;
ss << "Range [" << r[0] << ", " << r[1] << "] is out of domain bounds ["
<< domain[0] << ", " << domain[1] << "] on dimension '" << dim->name()
<< "'";
*err_msg = ss.str();
return false;
}

return true;
}

bool Dimension::check_range(const Range& range, std::string* err_msg) const {
assert(check_range_func_ != nullptr);
return check_range_func_(this, range, err_msg);
}

template <class T>
bool Dimension::coincides_with_tiles(const Dimension* dim, const Range& r) {
assert(dim != nullptr);
assert(!r.empty());
assert(dim->tile_extent() != nullptr);

auto dim_domain = (const T*)dim->domain();
auto tile_extent = *(const T*)dim->tile_extent();
auto d = (const T*)r.data();
auto norm_1 = uint64_t(d[0] - dim_domain[0]);
auto norm_2 = (uint64_t(d[1]) - dim_domain[0]) + 1;
return ((norm_1 / tile_extent) * tile_extent == norm_1) &&
((norm_2 / tile_extent) * tile_extent == norm_2);
}

bool Dimension::coincides_with_tiles(const Range& r) const {
assert(coincides_with_tiles_func_ != nullptr);
return coincides_with_tiles_func_(this, r);
}

template <class T>
void Dimension::compute_mbr(const Tile& tile, Range* mbr) {
assert(mbr != nullptr);
Expand Down Expand Up @@ -497,15 +559,15 @@ double Dimension::overlap_ratio(const Range& r1, const Range& r2) const {

template <class T>
void Dimension::split_range(
const void* r, const ByteVecValue& v, Range* r1, Range* r2) {
assert(r != nullptr);
const Range& r, const ByteVecValue& v, Range* r1, Range* r2) {
assert(!r.empty());
assert(!v.empty());
assert(r1 != nullptr);
assert(r2 != nullptr);

auto max = std::numeric_limits<T>::max();
bool int_domain = std::numeric_limits<T>::is_integer;
auto r_t = (const T*)r;
auto r_t = (const T*)r.data();
auto v_t = *(const T*)(&v[0]);

T ret[2];
Expand All @@ -518,7 +580,7 @@ void Dimension::split_range(
}

void Dimension::split_range(
const void* r, const ByteVecValue& v, Range* r1, Range* r2) const {
const Range& r, const ByteVecValue& v, Range* r1, Range* r2) const {
assert(split_range_func_ != nullptr);
split_range_func_(r, v, r1, r2);
}
Expand Down Expand Up @@ -1068,6 +1130,112 @@ void Dimension::set_ceil_to_tile_func() {
}
}

void Dimension::set_check_range_func() {
switch (type_) {
case Datatype::INT32:
check_range_func_ = check_range<int32_t>;
break;
case Datatype::INT64:
check_range_func_ = check_range<int64_t>;
break;
case Datatype::INT8:
check_range_func_ = check_range<int8_t>;
break;
case Datatype::UINT8:
check_range_func_ = check_range<uint8_t>;
break;
case Datatype::INT16:
check_range_func_ = check_range<int16_t>;
break;
case Datatype::UINT16:
check_range_func_ = check_range<uint16_t>;
break;
case Datatype::UINT32:
check_range_func_ = check_range<uint32_t>;
break;
case Datatype::UINT64:
check_range_func_ = check_range<uint64_t>;
break;
case Datatype::FLOAT32:
check_range_func_ = check_range<float>;
break;
case Datatype::FLOAT64:
check_range_func_ = check_range<double>;
break;
case Datatype::DATETIME_YEAR:
case Datatype::DATETIME_MONTH:
case Datatype::DATETIME_WEEK:
case Datatype::DATETIME_DAY:
case Datatype::DATETIME_HR:
case Datatype::DATETIME_MIN:
case Datatype::DATETIME_SEC:
case Datatype::DATETIME_MS:
case Datatype::DATETIME_US:
case Datatype::DATETIME_NS:
case Datatype::DATETIME_PS:
case Datatype::DATETIME_FS:
case Datatype::DATETIME_AS:
check_range_func_ = check_range<int64_t>;
break;
default:
check_range_func_ = nullptr;
break;
}
}

void Dimension::set_coincides_with_tiles_func() {
switch (type_) {
case Datatype::INT32:
coincides_with_tiles_func_ = coincides_with_tiles<int32_t>;
break;
case Datatype::INT64:
coincides_with_tiles_func_ = coincides_with_tiles<int64_t>;
break;
case Datatype::INT8:
coincides_with_tiles_func_ = coincides_with_tiles<int8_t>;
break;
case Datatype::UINT8:
coincides_with_tiles_func_ = coincides_with_tiles<uint8_t>;
break;
case Datatype::INT16:
coincides_with_tiles_func_ = coincides_with_tiles<int16_t>;
break;
case Datatype::UINT16:
coincides_with_tiles_func_ = coincides_with_tiles<uint16_t>;
break;
case Datatype::UINT32:
coincides_with_tiles_func_ = coincides_with_tiles<uint32_t>;
break;
case Datatype::UINT64:
coincides_with_tiles_func_ = coincides_with_tiles<uint64_t>;
break;
case Datatype::FLOAT32:
coincides_with_tiles_func_ = coincides_with_tiles<float>;
break;
case Datatype::FLOAT64:
coincides_with_tiles_func_ = coincides_with_tiles<double>;
break;
case Datatype::DATETIME_YEAR:
case Datatype::DATETIME_MONTH:
case Datatype::DATETIME_WEEK:
case Datatype::DATETIME_DAY:
case Datatype::DATETIME_HR:
case Datatype::DATETIME_MIN:
case Datatype::DATETIME_SEC:
case Datatype::DATETIME_MS:
case Datatype::DATETIME_US:
case Datatype::DATETIME_NS:
case Datatype::DATETIME_PS:
case Datatype::DATETIME_FS:
case Datatype::DATETIME_AS:
coincides_with_tiles_func_ = coincides_with_tiles<int64_t>;
break;
default:
coincides_with_tiles_func_ = nullptr;
break;
}
}

void Dimension::set_compute_mbr_func() {
switch (type_) {
case Datatype::INT32:
Expand Down
Loading

0 comments on commit be9efbd

Please sign in to comment.