/* * Tenant.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 "fdbclient/SystemData.h" #include "fdbclient/Tenant.h" #include "flow/UnitTest.h" Key TenantMapEntry::idToPrefix(int64_t id) { int64_t swapped = bigEndian64(id); return StringRef(reinterpret_cast(&swapped), 8); } int64_t TenantMapEntry::prefixToId(KeyRef prefix) { ASSERT(prefix.size() == 8); int64_t id = *reinterpret_cast(prefix.begin()); id = bigEndian64(id); ASSERT(id >= 0); return id; } void TenantMapEntry::initPrefix(KeyRef subspace) { ASSERT(id >= 0); prefix = makeString(8 + subspace.size()); uint8_t* data = mutateString(prefix); if (subspace.size() > 0) { memcpy(data, subspace.begin(), subspace.size()); } int64_t swapped = bigEndian64(id); memcpy(data + subspace.size(), &swapped, 8); } TenantMapEntry::TenantMapEntry() : id(-1) {} TenantMapEntry::TenantMapEntry(int64_t id, KeyRef subspace) : id(id) { initPrefix(subspace); } TEST_CASE("/fdbclient/TenantMapEntry/Serialization") { TenantMapEntry entry1(1, ""_sr); ASSERT(entry1.prefix == "\x00\x00\x00\x00\x00\x00\x00\x01"_sr); TenantMapEntry entry2 = TenantMapEntry::decode(entry1.encode()); ASSERT(entry1.id == entry2.id && entry1.prefix == entry2.prefix); TenantMapEntry entry3(std::numeric_limits::max(), "foo"_sr); ASSERT(entry3.prefix == "foo\x7f\xff\xff\xff\xff\xff\xff\xff"_sr); TenantMapEntry entry4 = TenantMapEntry::decode(entry3.encode()); ASSERT(entry3.id == entry4.id && entry3.prefix == entry4.prefix); for (int i = 0; i < 100; ++i) { int bits = deterministicRandom()->randomInt(1, 64); int64_t min = bits == 1 ? 0 : (UINT64_C(1) << (bits - 1)); int64_t maxPlusOne = std::min(UINT64_C(1) << bits, std::numeric_limits::max()); int64_t id = deterministicRandom()->randomInt64(min, maxPlusOne); int subspaceLength = deterministicRandom()->randomInt(0, 20); Standalone subspace = makeString(subspaceLength); generateRandomData(mutateString(subspace), subspaceLength); TenantMapEntry entry(id, subspace); int64_t bigEndianId = bigEndian64(id); ASSERT(entry.id == id && entry.prefix.startsWith(subspace) && entry.prefix.endsWith(StringRef(reinterpret_cast(&bigEndianId), 8)) && entry.prefix.size() == subspaceLength + 8); TenantMapEntry decodedEntry = TenantMapEntry::decode(entry.encode()); ASSERT(decodedEntry.id == entry.id && decodedEntry.prefix == entry.prefix); } return Void(); }