Skip to content

Commit

Permalink
Migrate APIs out of StorageManager: object_iter_*.
Browse files Browse the repository at this point in the history
  • Loading branch information
bekadavis9 committed Jun 7, 2024
1 parent 6300fbf commit 396e88d
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 267 deletions.
1 change: 1 addition & 0 deletions tiledb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ set(TILEDB_CORE_SOURCES
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/utils.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/misc/win_constants.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/object/object.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/object/object_iter.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/object/object_mutex.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/ast/query_ast.cc
${TILEDB_CORE_INCLUDE_DIR}/tiledb/sm/query/deletes_and_updates/deletes_and_updates.cc
Expand Down
26 changes: 13 additions & 13 deletions tiledb/sm/c_api/tiledb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "tiledb/sm/filter/filter_pipeline.h"
#include "tiledb/sm/misc/tdb_time.h"
#include "tiledb/sm/object/object.h"
#include "tiledb/sm/object/object_iter.h"
#include "tiledb/sm/query/query.h"
#include "tiledb/sm/query/query_condition.h"
#include "tiledb/sm/rest/rest_client.h"
Expand Down Expand Up @@ -3115,9 +3116,8 @@ int32_t tiledb_object_walk(
}

// Create an object iterator
tiledb::sm::StorageManager::ObjectIter* obj_iter;
throw_if_not_ok(ctx->storage_manager()->object_iter_begin(
&obj_iter, path, static_cast<tiledb::sm::WalkOrder>(order)));
tiledb::sm::ObjectIter* obj_iter = tiledb::sm::object_iter_begin(
ctx->resources(), path, static_cast<tiledb::sm::WalkOrder>(order));

// For as long as there is another object and the callback indicates to
// continue, walk over the TileDB objects in the path
Expand All @@ -3128,9 +3128,9 @@ int32_t tiledb_object_walk(
do {
if (SAVE_ERROR_CATCH(
ctx,
ctx->storage_manager()->object_iter_next(
obj_iter, &obj_name, &obj_type, &has_next))) {
ctx->storage_manager()->object_iter_free(obj_iter);
tiledb::sm::object_iter_next(
ctx->resources(), obj_iter, &obj_name, &obj_type, &has_next))) {
tiledb::sm::object_iter_free(obj_iter);
return TILEDB_ERR;
}
if (!has_next)
Expand All @@ -3139,7 +3139,7 @@ int32_t tiledb_object_walk(
} while (rc == 1);

// Clean up
ctx->storage_manager()->object_iter_free(obj_iter);
tiledb::sm::object_iter_free(obj_iter);

if (rc == -1)
return TILEDB_ERR;
Expand All @@ -3162,8 +3162,8 @@ int32_t tiledb_object_ls(
}

// Create an object iterator
tiledb::sm::StorageManager::ObjectIter* obj_iter;
throw_if_not_ok(ctx->storage_manager()->object_iter_begin(&obj_iter, path));
tiledb::sm::ObjectIter* obj_iter =
tiledb::sm::object_iter_begin(ctx->resources(), path);

// For as long as there is another object and the callback indicates to
// continue, walk over the TileDB objects in the path
Expand All @@ -3174,9 +3174,9 @@ int32_t tiledb_object_ls(
do {
if (SAVE_ERROR_CATCH(
ctx,
ctx->storage_manager()->object_iter_next(
obj_iter, &obj_name, &obj_type, &has_next))) {
ctx->storage_manager()->object_iter_free(obj_iter);
tiledb::sm::object_iter_next(
ctx->resources(), obj_iter, &obj_name, &obj_type, &has_next))) {
tiledb::sm::object_iter_free(obj_iter);
return TILEDB_ERR;
}
if (!has_next)
Expand All @@ -3185,7 +3185,7 @@ int32_t tiledb_object_ls(
} while (rc == 1);

// Clean up
ctx->storage_manager()->object_iter_free(obj_iter);
tiledb::sm::object_iter_free(obj_iter);

if (rc == -1)
return TILEDB_ERR;
Expand Down
220 changes: 220 additions & 0 deletions tiledb/sm/object/object_iter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* @file object_iter.cc
*
* @section LICENSE
*
* The MIT License
*
* @copyright Copyright (c) 2024 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 implements object iterator functions.
*/

#include "tiledb/sm/object/object_iter.h"
#include "tiledb/sm/enums/object_type.h"
#include "tiledb/sm/object/object.h"

namespace tiledb::sm {

class ObjectIterException : public StatusException {
public:
explicit ObjectIterException(const std::string& message)
: StatusException("ObjectIter", message) {
}
};

ObjectIter* object_iter_begin(
ContextResources& resources, const char* path, WalkOrder order) {
// Sanity check
URI path_uri(path);
if (path_uri.is_invalid()) {
throw ObjectIterException(
"Cannot create object iterator; Invalid input path");
}

// Get all contents of path
std::vector<URI> uris;
throw_if_not_ok(resources.vfs().ls(path_uri, &uris));

// Create a new object iterator
ObjectIter* obj_iter = tdb_new(ObjectIter);
obj_iter->order_ = order;
obj_iter->recursive_ = true;

// Include the uris that are TileDB objects in the iterator state
ObjectType obj_type;
for (auto& uri : uris) {
auto st = object_type(resources, uri, &obj_type);
if (!st.ok()) {
tdb_delete(obj_iter);
std::throw_with_nested(ObjectIterException(
"Cannot create object iterator; " + st.message()));
}
if (obj_type != ObjectType::INVALID) {
obj_iter->objs_.push_back(uri);
if (order == WalkOrder::POSTORDER)
obj_iter->expanded_.push_back(false);
}
}

return obj_iter;
}

ObjectIter* object_iter_begin(ContextResources& resources, const char* path) {
// Sanity check
URI path_uri(path);
if (path_uri.is_invalid()) {
throw ObjectIterException(
"Cannot create object iterator; Invalid input path");
}

// Get all contents of path
std::vector<URI> uris;
throw_if_not_ok(resources.vfs().ls(path_uri, &uris));

// Create a new object iterator
ObjectIter* obj_iter = tdb_new(ObjectIter);
obj_iter->order_ = WalkOrder::PREORDER;
obj_iter->recursive_ = false;

// Include the uris that are TileDB objects in the iterator state
ObjectType obj_type;
for (auto& uri : uris) {
throw_if_not_ok(object_type(resources, uri, &obj_type));
if (obj_type != ObjectType::INVALID) {
obj_iter->objs_.push_back(uri);
}
}

return obj_iter;
}

void object_iter_free(ObjectIter* obj_iter) {
tdb_delete(obj_iter);
}

Status object_iter_next(
ContextResources& resources,
ObjectIter* obj_iter,
const char** path,
ObjectType* type,
bool* has_next) {
// Handle case there is no next
if (obj_iter->objs_.empty()) {
*has_next = false;
return Status::Ok();
}

// Retrieve next object
switch (obj_iter->order_) {
case WalkOrder::PREORDER:
RETURN_NOT_OK(
object_iter_next_preorder(resources, obj_iter, path, type, has_next));
break;
case WalkOrder::POSTORDER:
RETURN_NOT_OK(object_iter_next_postorder(
resources, obj_iter, path, type, has_next));
break;
}

return Status::Ok();
}

Status object_iter_next_postorder(
ContextResources& resources,
ObjectIter* obj_iter,
const char** path,
ObjectType* type,
bool* has_next) {
// Get all contents of the next URI recursively till the bottom,
// if the front of the list has not been expanded
if (obj_iter->expanded_.front() == false) {
uint64_t obj_num;
do {
obj_num = obj_iter->objs_.size();
std::vector<URI> uris;
throw_if_not_ok(resources.vfs().ls(obj_iter->objs_.front(), &uris));
obj_iter->expanded_.front() = true;

// Push the new TileDB objects in the front of the iterator's list
ObjectType obj_type;
for (auto it = uris.rbegin(); it != uris.rend(); ++it) {
throw_if_not_ok(object_type(resources, *it, &obj_type));
if (obj_type != ObjectType::INVALID) {
obj_iter->objs_.push_front(*it);
obj_iter->expanded_.push_front(false);
}
}
} while (obj_num != obj_iter->objs_.size());
}

// Prepare the values to be returned
URI front_uri = obj_iter->objs_.front();
obj_iter->next_ = front_uri.to_string();
throw_if_not_ok(object_type(resources, front_uri, type));
*path = obj_iter->next_.c_str();
*has_next = true;

// Pop the front (next URI) of the iterator's object list
obj_iter->objs_.pop_front();
obj_iter->expanded_.pop_front();

return Status::Ok();
}

Status object_iter_next_preorder(
ContextResources& resources,
ObjectIter* obj_iter,
const char** path,
ObjectType* type,
bool* has_next) {
// Prepare the values to be returned
URI front_uri = obj_iter->objs_.front();
obj_iter->next_ = front_uri.to_string();
throw_if_not_ok(object_type(resources, front_uri, type));
*path = obj_iter->next_.c_str();
*has_next = true;

// Pop the front (next URI) of the iterator's object list
obj_iter->objs_.pop_front();

// Return if no recursion is needed
if (!obj_iter->recursive_)
return Status::Ok();

// Get all contents of the next URI
std::vector<URI> uris;
throw_if_not_ok(resources.vfs().ls(front_uri, &uris));

// Push the new TileDB objects in the front of the iterator's list
ObjectType obj_type;
for (auto it = uris.rbegin(); it != uris.rend(); ++it) {
throw_if_not_ok(object_type(resources, *it, &obj_type));
if (obj_type != ObjectType::INVALID)
obj_iter->objs_.push_front(*it);
}

return Status::Ok();
}

} // namespace tiledb::sm
Loading

0 comments on commit 396e88d

Please sign in to comment.