Refactor Tenant class in fdb_api header to match conventions of existing classes and move tenant creation into populate function

This commit is contained in:
Jon Fu 2022-05-20 13:03:59 -04:00
parent cdca68e26a
commit b92b3b21b0
5 changed files with 48 additions and 100 deletions

View File

@ -112,7 +112,7 @@ if(NOT WIN32)
test/unit/fdb_api.hpp)
add_library(fdb_cpp INTERFACE)
target_sources(fdb_cpp INTERFACE test/fdb_api.hpp test/fdb_api.cpp)
target_sources(fdb_cpp INTERFACE test/fdb_api.hpp)
target_include_directories(fdb_cpp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/test)
target_link_libraries(fdb_cpp INTERFACE fmt::fmt)

View File

@ -1,29 +0,0 @@
/*
* fdb_api.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fdb_api.hpp"
#include <iostream>
namespace fdb {
const std::string Tenant::tenantManagementMapPrefix = "\xff\xff/management/tenant_map/";
} // namespace fdb

View File

@ -23,7 +23,7 @@
#pragma once
#ifndef FDB_API_VERSION
#define FDB_API_VERSION 710
#define FDB_API_VERSION 720
#endif
#include <cassert>
@ -560,55 +560,42 @@ public:
};
class Tenant final {
static const std::string tenantManagementMapPrefix;
static const std::string tenantMapPrefix;
std::shared_ptr<native::FDBTenant> tenant;
static constexpr CharsRef tenantManagementMapPrefix = "\xff\xff/management/tenant_map/";
public:
static TypedFuture<future_var::None> createTenant(Transaction tr, std::string name) {
Tenant(const Tenant&) noexcept = default;
Tenant& operator=(const Tenant&) noexcept = default;
Tenant(fdb::Database* db, BytesRef name, int name_length) : tenant(nullptr) {
auto tenant_raw = static_cast<native::FDBTenant*>(nullptr);
if (auto err = Error(native::fdb_database_open_tenant(db->db.get(), name.data(), name_length, &tenant_raw))) {
throwError(fmt::format("Failed to create tenant with name '{}': ", name), err);
}
tenant = std::shared_ptr<native::FDBTenant>(tenant_raw, &native::fdb_tenant_destroy);
}
Tenant() noexcept : tenant(nullptr) {}
static void createTenant(Transaction tr, BytesRef name) {
tr.setOption(FDBTransactionOption::FDB_TR_OPTION_SPECIAL_KEY_SPACE_ENABLE_WRITES, 1);
tr.setOption(FDBTransactionOption::FDB_TR_OPTION_LOCK_AWARE, 1);
KeyRef tenantManagementKey = toBytesRef(tenantManagementMapPrefix + name);
tr.set(tenantManagementKey, toBytesRef(std::string("")));
return tr.commit();
tr.set(toBytesRef(fmt::format("{}{}", tenantManagementMapPrefix, toCharsRef(name))),
toBytesRef(std::string("")));
}
static TypedFuture<future_var::None> deleteTenant(Transaction tr, std::string name) {
static void deleteTenant(Transaction tr, BytesRef name) {
tr.setOption(FDBTransactionOption::FDB_TR_OPTION_RAW_ACCESS, 1);
tr.setOption(FDBTransactionOption::FDB_TR_OPTION_LOCK_AWARE, 1);
KeyRef tenantManagementKey = toBytesRef(tenantManagementMapPrefix + name);
tr.clear(tenantManagementKey);
return tr.commit();
}
Tenant(fdb::Database* db, const uint8_t* name, int name_length) {
if (native::fdb_error_t err = fdb_database_open_tenant(db->db.get(), name, name_length, &tenant)) {
std::cerr << native::fdb_get_error(err) << std::endl;
std::abort();
}
}
~Tenant() {
if (tenant != nullptr) {
fdb_tenant_destroy(tenant);
}
tr.clear(toBytesRef(fmt::format("{}{}", tenantManagementMapPrefix, toCharsRef(name))));
}
Transaction createTransaction() {
auto tx_native = static_cast<native::FDBTransaction*>(nullptr);
auto err = Error(native::fdb_tenant_create_transaction(tenant, &tx_native));
auto err = Error(native::fdb_tenant_create_transaction(tenant.get(), &tx_native));
if (err)
throwError("Failed to create transaction: ", err);
return Transaction(tx_native);
}
Tenant(const Tenant&) = delete;
Tenant& operator=(const Tenant&) = delete;
Tenant(Tenant&&) = delete;
Tenant& operator=(Tenant&&) = delete;
private:
friend class Transaction;
native::FDBTenant* tenant;
};
} // namespace fdb

View File

@ -78,15 +78,15 @@ using namespace mako;
thread_local Logger logr = Logger(MainProcess{}, VERBOSE_DEFAULT);
Transaction createNewTransaction(Database* db, Arguments const& args, int id = -1) {
Transaction createNewTransaction(Database db, Arguments const& args, int id = -1) {
// No tenants specified
if (args.tenants <= 0) {
return db->createTransaction();
return db.createTransaction();
}
// Create Tenant Transaction
int tenant_id = (id == -1) ? urand(1, args.tenants) : id;
std::string tenant_name = "tenant" + std::to_string(tenant_id);
Tenant t(db, reinterpret_cast<const uint8_t*>(tenant_name.c_str()), tenant_name.length());
BytesRef tenant_name = toBytesRef("tenant" + std::to_string(tenant_id));
Tenant t(&db, tenant_name, tenant_name.length());
return t.createTransaction();
}
@ -115,7 +115,7 @@ int cleanup(Database db, Arguments const& args) {
// If args.tenants is zero, this will use a non-tenant txn and perform a single range clear.
// If 1, it will use a tenant txn and do a single range clear instead.
// If > 1, it will perform a range clear with a different tenant txn per iteration.
Transaction tx = createNewTransaction(&db, args, i);
Transaction tx = createNewTransaction(db, args, i);
while (true) {
tx.clearRange(beginstr, endstr);
auto future_commit = tx.commit();
@ -132,19 +132,16 @@ int cleanup(Database db, Arguments const& args) {
// If tenants are specified, also delete the tenant after clearing out its keyspace
if (args.tenants > 0) {
std::string tenant_name = "tenant" + std::to_string(i);
while (true) {
Transaction systemTx = db.createTransaction();
auto future_commit = Tenant::deleteTenant(systemTx, tenant_name);
Tenant::deleteTenant(systemTx, toBytesRef("tenant" + std::to_string(i)));
auto future_commit = systemTx.commit();
const auto rc = waitAndHandleError(systemTx, future_commit, "DELETE_TENANT");
if (rc == FutureRC::OK) {
break;
} else if (rc == FutureRC::RETRY || rc == FutureRC::CONFLICT) {
// tx already reset
continue;
} else {
// try with new transaction object
systemTx = db.createTransaction();
}
}
}
@ -178,7 +175,23 @@ int populate(Database db,
auto watch_trace = Stopwatch(watch_total.getStart());
auto key_checkpoint = key_begin; // in case of commit failure, restart from this key
Transaction tx = createNewTransaction(&db, args);
Transaction systemTx = db.createTransaction();
for (int i = 1; i <= args.tenants; ++i) {
std::string tenant_name = "tenant" + std::to_string(i);
Tenant::createTenant(systemTx, toBytesRef(tenant_name));
while (i % 10 == 0 || i == args.tenants) {
// create {batchSize} # of tenants
// commit every batch
auto future_commit = systemTx.commit();
const auto rc = waitAndHandleError(systemTx, future_commit, "CREATE_TENANT");
if (rc == FutureRC::OK) {
systemTx.reset();
break;
}
// look up tenant range limit 1. If found, break, else retry
}
}
Transaction tx = createNewTransaction(db, args);
for (auto i = key_begin; i <= key_end; i++) {
/* sequential keys */
genKey(keystr.data(), KEY_PREFIX, args, i);
@ -224,7 +237,7 @@ int populate(Database db,
auto tx_restarter = ExitGuard([&watch_tx]() { watch_tx.startFromStop(); });
if (rc == FutureRC::OK) {
key_checkpoint = i + 1; // restart on failures from next key
tx = createNewTransaction(&db, args);
tx = createNewTransaction(db, args);
} else if (rc == FutureRC::ABORT) {
return -1;
} else {
@ -410,7 +423,7 @@ int runWorkload(Database db,
/* main transaction loop */
while (1) {
Transaction tx = createNewTransaction(&db, args);
Transaction tx = createNewTransaction(db, args);
while ((thread_tps > 0) && (xacts >= current_tps)) {
/* throttle on */
const auto time_now = steady_clock::now();
@ -615,29 +628,6 @@ void workerThread(ThreadArgs& thread_args) {
? -1
: computeThreadIters(args.iteration, worker_id, thread_id, args.num_processes, args.num_threads);
/* create my own transaction object */
Transaction tx;
tx = database.createTransaction();
if (tenant_main && tenants > 0) {
for (int i = 1; i <= tenants; ++i) {
std::string tenant_name = "tenant" + std::to_string(i);
while (true) {
auto future_commit = Tenant::createTenant(tx, tenant_name);
const auto rc = waitAndHandleError(tx, future_commit, "CREATE_TENANT");
if (rc == FutureRC::OK) {
break;
} else if (rc == FutureRC::RETRY || rc == FutureRC::CONFLICT) {
// tx already reset
continue;
} else {
// try with new transaction object
tx = database.createTransaction();
}
}
}
}
/* i'm ready */
readycount.fetch_add(1);
auto stopcount_guard = ExitGuard([&stopcount]() { stopcount.fetch_add(1); });

View File

@ -22,7 +22,7 @@
#define MAKO_HPP
#ifndef FDB_API_VERSION
#define FDB_API_VERSION 710
#define FDB_API_VERSION 720
#endif
#include <array>