Skip to content

Commit

Permalink
new api function to pass blob references
Browse files Browse the repository at this point in the history
  • Loading branch information
kuron99 committed Jan 17, 2025
1 parent d088faf commit 189441e
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 11 deletions.
35 changes: 35 additions & 0 deletions include/sharksfin/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ using commit_callback_type = std::function<void(StatusCode, ErrorCode, durabilit
*/
using durability_callback_type = std::function<void(durability_marker_type)>;

/**
* @brief BLOB reference type.
* @details the reference type for BLOB data. This must be same as one defined by datastore.
*/
using blob_id_type = std::uint64_t;

/**
* @brief opens a database and returns its handle.
* The created handle must be disposed by database_dispose().
Expand Down Expand Up @@ -654,6 +660,35 @@ extern "C" StatusCode content_put(
Slice value,
PutOperation operation = PutOperation::CREATE_OR_UPDATE);

/**
* @brief puts a content onto the target key possibly with blob ids that are used in the content
* @param transaction the current transaction handle
* @param storage the target storage
* @param key the content key
* @param value the content value
* @param blobs_data list of blob reference id that are used by the entry under put operation
* @param blobs_size the length of the blob reference id list
* @param operation indicates the behavior with the existing/new entry. See PutOperation.
* @return StatusCode::OK if the target content was successfully put
* @return StatusCode::ERR_INACTIVE_TRANSACTION if the transaction is inactive and the request is rejected
* @return StatusCode::PREMATURE if the transaction is not ready to accept request
* @return StatusCode::CONCURRENT_OPERATION if `operation` is `CREATE` and other concurrent operation is observed.
* The transaction is still active (i.e. not aborted). Retrying the request might be successful if the concurrent
* operation complete, or doesn't exist any more.
* @return StatusCode::ERR_ILLEGAL_OPERATION if the transaction is read-only
* @return StatusCode::ERR_INVALID_KEY_LENGTH if the key length is invalid (e.g. too long) to be handled by transaction engine
* @return warnings if the operation is not applicable to the entry. See PutOperation.
* @return otherwise if error was occurred
*/
extern "C" StatusCode content_put_with_blobs(
TransactionHandle transaction,
StorageHandle storage,
Slice key,
Slice value,
blob_id_type const* blobs_data,
std::size_t blobs_size,
PutOperation operation = PutOperation::CREATE_OR_UPDATE);

/**
* @brief removes a content on the target key.
* @param transaction the current transaction handle
Expand Down
18 changes: 18 additions & 0 deletions memory/src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,24 @@ StatusCode content_put(
return rc;
}

StatusCode content_put_with_blobs(
TransactionHandle transaction,
StorageHandle storage,
Slice key,
Slice value,
blob_id_type const* blobs_data,
std::size_t blobs_size,
PutOperation operation) {
// currently nothing is implemented to handle blobs
(void) blobs_data;
(void) blobs_size;
log_entry << fn_name << " transaction:" << transaction << " storage:" << storage << binstring(key) << binstring(value) << " operation:" << operation;
auto rc = impl::content_put(transaction, storage, key, value, operation);
log_rc(rc, fn_name);
log_exit << fn_name << " rc:" << rc;
return rc;
}

StatusCode content_delete(
TransactionHandle transaction,
StorageHandle storage,
Expand Down
37 changes: 37 additions & 0 deletions memory/test/ApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1554,5 +1554,42 @@ TEST_F(ApiTest, write_by_readonly_transaction) {
EXPECT_EQ(database_close(db), StatusCode::OK);
}

TEST_F(ApiTest, put_with_blobs) {
// currently test just calling content_put_with_blobs
DatabaseOptions options;
DatabaseHandle db;
ASSERT_EQ(database_open(options, &db), StatusCode::OK);
HandleHolder dbh { db };

struct S {
static TransactionOperation f1(TransactionHandle tx, void* args) {
std::vector<blob_id_type> blobs{1, 2, 3, 4};
auto st = extract<S>(args);
if (content_put_with_blobs(tx, st, "a", "A", blobs.data(), blobs.size()) != StatusCode::OK) {
return TransactionOperation::ERROR;
}
return TransactionOperation::COMMIT;
}
static TransactionOperation f2(TransactionHandle tx, void* args) {
auto st = extract<S>(args);
Slice s;
if (content_get(tx, st, "a", &s) != StatusCode::OK) {
return TransactionOperation::ERROR;
}
if (s != "A") {
return TransactionOperation::ERROR;
}
return TransactionOperation::COMMIT;
}
StorageHandle st;
};
S s;
ASSERT_EQ(storage_create(db, "s", &s.st), StatusCode::OK);
HandleHolder sth { s.st };

EXPECT_EQ(transaction_exec(db, {}, &S::f1, &s), StatusCode::OK);
EXPECT_EQ(transaction_exec(db, {}, &S::f2, &s), StatusCode::OK);
EXPECT_EQ(database_close(db), StatusCode::OK);
}

} // namespace sharksfin
10 changes: 6 additions & 4 deletions shirakami/src/Storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ StatusCode Storage::get(Transaction* tx, Slice key, std::string &buffer) { //NO
return resolve(res);
}

StatusCode Storage::put(Transaction* tx, Slice key, Slice value, PutOperation operation) {//NOLINT(readability-make-member-function-const)
StatusCode Storage::put(Transaction *tx, Slice key, Slice value, PutOperation operation,

Check warning on line 44 in shirakami/src/Storage.cpp

View workflow job for this annotation

GitHub Actions / Clang-Tidy

readability-make-member-function-const

method 'put' can be made const
blob_id_type const *blobs_data,
std::size_t blobs_size) { // NOLINT(readability-make-member-function-const)
if(! tx->active()) return StatusCode::ERR_INACTIVE_TRANSACTION;
Status res{};
switch(operation) {
case PutOperation::CREATE: res = api::insert(*tx, handle_, key.to_string_view(), value.to_string_view()); break;
case PutOperation::UPDATE: res = api::update(*tx, handle_, key.to_string_view(), value.to_string_view()); break;
case PutOperation::CREATE_OR_UPDATE: res = api::upsert(*tx, handle_, key.to_string_view(), value.to_string_view()); break;
case PutOperation::CREATE: res = api::insert(*tx, handle_, key.to_string_view(), value.to_string_view(), blobs_data, blobs_size); break;
case PutOperation::UPDATE: res = api::update(*tx, handle_, key.to_string_view(), value.to_string_view(), blobs_data, blobs_size); break;
case PutOperation::CREATE_OR_UPDATE: res = api::upsert(*tx, handle_, key.to_string_view(), value.to_string_view(), blobs_data, blobs_size); break;
}
tx->last_call_status(res);
correct_transaction_state(*tx, res);
Expand Down
6 changes: 5 additions & 1 deletion shirakami/src/Storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,13 @@ class Storage {
* @param key the entry key
* @param value the entry value
* @param operation type of the put operation
* @param blobs_data the list of blob refs used
* @param blobs_size the length of the list
* @return the operation status
*/
StatusCode put(Transaction* tx, Slice key, Slice value, PutOperation operation = PutOperation::CREATE_OR_UPDATE);
StatusCode put(Transaction *tx, Slice key, Slice value, PutOperation operation = PutOperation::CREATE_OR_UPDATE,
blob_id_type const *blobs_data = nullptr,
std::size_t blobs_size = 0);

/**
* @brief removes an entry.
Expand Down
18 changes: 18 additions & 0 deletions shirakami/src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,24 @@ StatusCode content_put(
return stg->put(tx, key, value, operation);
}

StatusCode content_put_with_blobs(
TransactionHandle transaction,
StorageHandle storage,
Slice key,
Slice value,
blob_id_type const* blobs_data,
std::size_t blobs_size,
PutOperation operation) {
auto tx = unwrap(transaction);
if (! tx->active()) return StatusCode::ERR_INACTIVE_TRANSACTION;
auto stg = unwrap(storage);
auto db = tx->owner();
if (!db) {
return StatusCode::ERR_INVALID_STATE;
}
return stg->put(tx, key, value, operation, blobs_data, blobs_size);
}

StatusCode content_delete(
TransactionHandle transaction,
StorageHandle storage,
Expand Down
12 changes: 9 additions & 3 deletions shirakami/src/shirakami_api_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ Status storage_set_options(::shirakami::Storage storage, storage_option const& o
return rc;
}

Status insert(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val) {
Status insert(Transaction &tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
[[maybe_unused]] blob_id_type const *blobs_data,
[[maybe_unused]] std::size_t blobs_size) {
log_entry <<
"token:" << tx.native_handle() << " storage:" << storage << binstring(key) << binstring(val);
auto rc = details::sanitize_rc(::shirakami::insert(tx.native_handle(), storage, key, val));
Expand All @@ -187,7 +189,9 @@ Status insert(Transaction& tx, ::shirakami::Storage storage, std::string_view ke
return rc;
}

Status update(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val) {
Status update(Transaction &tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
[[maybe_unused]] blob_id_type const *blobs_data,
[[maybe_unused]] std::size_t blobs_size) {
log_entry
<< "token:" << tx.native_handle() << " storage:" << storage << binstring(key) << binstring(val);
auto rc = details::sanitize_rc(::shirakami::update(tx.native_handle(), storage, key, val));
Expand All @@ -208,7 +212,9 @@ Status update(Transaction& tx, ::shirakami::Storage storage, std::string_view ke
return rc;
}

Status upsert(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val) {
Status upsert(Transaction &tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
[[maybe_unused]] blob_id_type const *blobs_data,
[[maybe_unused]] std::size_t blobs_size) {
log_entry
<< "token:" << tx.native_handle() << " storage:" << storage << binstring(key) << binstring(val);
auto rc = details::sanitize_rc(::shirakami::upsert(tx.native_handle(), storage, key, val));
Expand Down
10 changes: 7 additions & 3 deletions shirakami/src/shirakami_api_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using scan_endpoint = ::shirakami::scan_endpoint;
using transaction_options = ::shirakami::transaction_options;
using storage_option = ::shirakami::storage_option;
using read_area = ::shirakami::transaction_options::read_area;
using blob_id_type = ::shirakami::blob_id_type;

class Transaction;

Expand Down Expand Up @@ -95,11 +96,14 @@ Status storage_get_options(::shirakami::Storage storage, storage_option& options

Status storage_set_options(::shirakami::Storage storage, storage_option const& options);

Status insert(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val);
Status insert(Transaction &tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
blob_id_type const* blobs_data, std::size_t blobs_size);

Status upsert(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val);
Status upsert(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
blob_id_type const* blobs_data, std::size_t blobs_size);

Status update(Transaction& tx, ::shirakami::Storage storage, std::string_view key, std::string_view val);
Status update(Transaction &tx, ::shirakami::Storage storage, std::string_view key, std::string_view val,
blob_id_type const* blobs_data, std::size_t blobs_size);

Status delete_storage(::shirakami::Storage storage);

Expand Down
40 changes: 40 additions & 0 deletions shirakami/test/ApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2202,4 +2202,44 @@ TEST_F(ShirakamiApiTest, get_data_store) {
}
}

TEST_F(ShirakamiApiTest, put_with_blobs) {
// currently test just calling content_put_with_blobs
DatabaseOptions options;
options.attribute(KEY_LOCATION, path());

DatabaseHandle db;
ASSERT_EQ(database_open(options, &db), StatusCode::OK);
HandleHolder dbh { db };

struct S {
static TransactionOperation f1(TransactionHandle tx, void* args) {
std::vector<blob_id_type> blobs{1, 2, 3, 4};
auto st = extract<S>(args);
if (content_put_with_blobs(tx, st, "a", "A", blobs.data(), blobs.size()) != StatusCode::OK) {
return TransactionOperation::ERROR;
}
return TransactionOperation::COMMIT;
}
static TransactionOperation f2(TransactionHandle tx, void* args) {
auto st = extract<S>(args);
Slice s;
if (content_get(tx, st, "a", &s) != StatusCode::OK) {
return TransactionOperation::ERROR;
}
if (s != "A") {
return TransactionOperation::ERROR;
}
return TransactionOperation::COMMIT;
}
StorageHandle st;
};
S s;
ASSERT_EQ(storage_create(db, "s", &s.st), StatusCode::OK);
HandleHolder sth { s.st };

EXPECT_EQ(transaction_exec(db, {}, &S::f1, &s), StatusCode::OK);
EXPECT_EQ(transaction_exec(db, {}, &S::f2, &s), StatusCode::OK);
EXPECT_EQ(database_close(db), StatusCode::OK);
}

} // namespace sharksfin

0 comments on commit 189441e

Please sign in to comment.