mirror of
https://github.com/apple/foundationdb.git
synced 2025-06-02 03:12:12 +08:00
Add a new C unit test that uses tenants. Fix simulation issue where resetting a transaction could cause in-flight operations to pick up the simulated default tenant for the next retry. Use the new list tenant JSON format in the tenant management test. Fix missing raw_access option in special key space correctness test.
This commit is contained in:
parent
4079b9f23d
commit
513e8887dd
bindings/c/test/unit
fdbclient
fdbserver/workloads
tests/TestRunner
@ -130,8 +130,15 @@ EmptyFuture Database::create_snapshot(FDBDatabase* db,
|
||||
return EmptyFuture(fdb_database_create_snapshot(db, uid, uid_length, snap_command, snap_command_length));
|
||||
}
|
||||
|
||||
// Transaction
|
||||
// Tenant
|
||||
Tenant::Tenant(FDBDatabase* db, const uint8_t* name, int name_length) {
|
||||
if (fdb_error_t err = fdb_database_open_tenant(db, name, name_length, &tenant)) {
|
||||
std::cerr << fdb_get_error(err) << std::endl;
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
// Transaction
|
||||
Transaction::Transaction(FDBDatabase* db) {
|
||||
if (fdb_error_t err = fdb_database_create_transaction(db, &tr_)) {
|
||||
std::cerr << fdb_get_error(err) << std::endl;
|
||||
@ -139,6 +146,13 @@ Transaction::Transaction(FDBDatabase* db) {
|
||||
}
|
||||
}
|
||||
|
||||
Transaction::Transaction(Tenant tenant) {
|
||||
if (fdb_error_t err = fdb_tenant_create_transaction(tenant.tenant, &tr_)) {
|
||||
std::cerr << fdb_get_error(err) << std::endl;
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
Transaction::~Transaction() {
|
||||
fdb_transaction_destroy(tr_);
|
||||
}
|
||||
|
@ -203,6 +203,15 @@ public:
|
||||
int snap_command_length);
|
||||
};
|
||||
|
||||
class Tenant final {
|
||||
public:
|
||||
Tenant(FDBDatabase* db, const uint8_t* name, int name_length);
|
||||
|
||||
private:
|
||||
friend class Transaction;
|
||||
FDBTenant* tenant;
|
||||
};
|
||||
|
||||
// Wrapper around FDBTransaction, providing the same set of calls as the C API.
|
||||
// Handles cleanup of memory, removing the need to call
|
||||
// fdb_transaction_destroy.
|
||||
@ -210,6 +219,7 @@ class Transaction final {
|
||||
public:
|
||||
// Given an FDBDatabase, initializes a new transaction.
|
||||
Transaction(FDBDatabase* db);
|
||||
Transaction(Tenant tenant);
|
||||
~Transaction();
|
||||
|
||||
// Wrapper around fdb_transaction_reset.
|
||||
|
@ -2410,6 +2410,112 @@ TEST_CASE("Fast alloc thread cleanup") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Tenant create, access, and delete") {
|
||||
std::string tenantName = "tenant";
|
||||
std::string testKey = "foo";
|
||||
std::string testValue = "bar";
|
||||
|
||||
fdb::Transaction tr(db);
|
||||
while (1) {
|
||||
fdb_check(tr.set_option(FDB_TR_OPTION_SPECIAL_KEY_SPACE_ENABLE_WRITES, nullptr, 0));
|
||||
fprintf(stderr, "Create tenant\n");
|
||||
tr.set("\xff\xff/management/tenant_map/" + tenantName, "");
|
||||
fdb::EmptyFuture commitFuture = tr.commit();
|
||||
fdb_error_t err = wait_future(commitFuture);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err) {
|
||||
fdb::EmptyFuture f = tr.on_error(err);
|
||||
fdb_check(wait_future(f));
|
||||
continue;
|
||||
}
|
||||
tr.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
fdb::Tenant tenant(db, reinterpret_cast<const uint8_t*>(tenantName.c_str()), tenantName.size());
|
||||
fdb::Transaction tr2(tenant);
|
||||
|
||||
while (1) {
|
||||
fprintf(stderr, "Set tenant key\n");
|
||||
tr2.set(testKey, testValue);
|
||||
fdb::EmptyFuture commitFuture = tr2.commit();
|
||||
fdb_error_t err = wait_future(commitFuture);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err) {
|
||||
fdb::EmptyFuture f = tr2.on_error(err);
|
||||
fdb_check(wait_future(f));
|
||||
continue;
|
||||
}
|
||||
tr2.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
fprintf(stderr, "Get tenant key\n");
|
||||
fdb::ValueFuture f1 = tr2.get(testKey, false);
|
||||
fdb_error_t err = wait_future(f1);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err) {
|
||||
fdb::EmptyFuture f2 = tr.on_error(err);
|
||||
fdb_check(wait_future(f2));
|
||||
continue;
|
||||
}
|
||||
|
||||
int out_present;
|
||||
char* val;
|
||||
int vallen;
|
||||
fdb_check(f1.get(&out_present, (const uint8_t**)&val, &vallen));
|
||||
CHECK(out_present == 1);
|
||||
CHECK(vallen == testValue.size());
|
||||
CHECK(testValue == val);
|
||||
|
||||
tr2.clear(testKey);
|
||||
fdb::EmptyFuture commitFuture = tr2.commit();
|
||||
err = wait_future(commitFuture);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err) {
|
||||
fdb::EmptyFuture f = tr2.on_error(err);
|
||||
fdb_check(wait_future(f));
|
||||
continue;
|
||||
}
|
||||
|
||||
tr2.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
fdb_check(tr.set_option(FDB_TR_OPTION_SPECIAL_KEY_SPACE_ENABLE_WRITES, nullptr, 0));
|
||||
fprintf(stderr, "Delete tenant\n");
|
||||
tr.clear("\xff\xff/management/tenant_map/" + tenantName);
|
||||
fdb::EmptyFuture commitFuture = tr.commit();
|
||||
fdb_error_t err = wait_future(commitFuture);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err) {
|
||||
fdb::EmptyFuture f = tr.on_error(err);
|
||||
fdb_check(wait_future(f));
|
||||
continue;
|
||||
}
|
||||
tr.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
fprintf(stderr, "Get tenant after delete\n");
|
||||
fdb::ValueFuture f1 = tr2.get(testKey, false);
|
||||
fdb_error_t err = wait_future(f1);
|
||||
fprintf(stderr, "Got error: %d\n", err);
|
||||
if (err == error_code_tenant_not_found) {
|
||||
tr2.reset();
|
||||
break;
|
||||
}
|
||||
if (err) {
|
||||
fdb::EmptyFuture f2 = tr.on_error(err);
|
||||
fdb_check(wait_future(f2));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 3) {
|
||||
std::cout << "Unit tests for the FoundationDB C API.\n"
|
||||
|
@ -3046,6 +3046,7 @@ Reference<TransactionState> TransactionState::cloneAndReset(Reference<Transactio
|
||||
newState->startTime = startTime;
|
||||
newState->committedVersion = committedVersion;
|
||||
newState->conflictingKeys = conflictingKeys;
|
||||
newState->tenantSet = tenantSet;
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
@ -1145,6 +1145,7 @@ struct SpecialKeySpaceCorrectnessWorkload : TestWorkload {
|
||||
}
|
||||
// advanceversion
|
||||
try {
|
||||
tx->setOption(FDBTransactionOptions::RAW_ACCESS);
|
||||
Version v1 = wait(tx->getReadVersion());
|
||||
TraceEvent(SevDebug, "InitialReadVersion").detail("Version", v1);
|
||||
state Version v2 = 2 * v1;
|
||||
|
@ -376,7 +376,7 @@ struct TenantManagementWorkload : TestWorkload {
|
||||
jsonDoc.get("id", id);
|
||||
jsonDoc.get("prefix", prefix);
|
||||
|
||||
Key prefixKey = KeyRef(unprintable(prefix));
|
||||
Key prefixKey = KeyRef(prefix);
|
||||
TenantMapEntry entry(id, prefixKey.substr(0, prefixKey.size() - 8));
|
||||
|
||||
ASSERT(entry.prefix == prefixKey);
|
||||
|
@ -136,5 +136,5 @@ logdir = {logdir}
|
||||
|
||||
def create_database(self, storage='ssd'):
|
||||
args = [self.fdbcli_binary, '-C', self.etc.joinpath('fdb.cluster'), '--exec',
|
||||
'configure new single {}'.format(storage)]
|
||||
'configure new single {} tenant_mode=optional_experimental'.format(storage)]
|
||||
subprocess.run(args)
|
||||
|
Loading…
x
Reference in New Issue
Block a user