Skip to content

Commit 297f701

Browse files
simonhollismeta-codesync[bot]
authored andcommitted
Add JustKnobs '64_bit_ids' to gate new db format
Summary: # What Put 64-bit db generation behind a JK for deployment safety. # Stack This is diff (3/4) Reviewed By: iamirzhan Differential Revision: D88260777 fbshipit-source-id: b23f8ffc67f590f208fd27b8f0e357864c9c88d2
1 parent 04f52c5 commit 297f701

File tree

2 files changed

+133
-31
lines changed

2 files changed

+133
-31
lines changed

glean/rocksdb/database-impl.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#include "glean/rts/timer.h"
1313

14+
#ifndef OSS
15+
#include "justknobs/JustKnobProxy.h"
16+
#endif
17+
1418
namespace facebook {
1519
namespace glean {
1620
namespace rocks {
@@ -147,16 +151,36 @@ DatabaseImpl::DatabaseImpl(
147151
}
148152

149153
// Initialize ownership format version
150-
// For new DBs: write the current (64-bit) format version
151-
// For existing DBs: if no version marker exists, assume 32-bit format
152-
ownership_format_version = static_cast<uint32_t>(initAdminValue(
153-
container_,
154-
AdminId::OWNERSHIP_FORMAT_VERSION,
155-
static_cast<uint64_t>(
156-
container_.mode == Mode::Create ? OWNERSHIP_FORMAT_VERSION_CURRENT
157-
: OWNERSHIP_FORMAT_VERSION_32BIT),
158-
container_.mode == Mode::Create,
159-
[] {}));
154+
// For new DBs: Check JustKnob to decide whether to use 64-bit or 32-bit
155+
// format. For existing DBs: if no version marker exists, assume 32-bit format
156+
// Both formats are always readable regardless of gatekeeper value
157+
if (container_.mode == Mode::Create) {
158+
// New DB: check JustKnob to determine format
159+
#ifndef OSS
160+
static facebook::jk::BooleanKnob use64BitOwnership(
161+
"glean/ownership:64_bit_ids");
162+
uint32_t format_to_use = use64BitOwnership()
163+
? OWNERSHIP_FORMAT_VERSION_64BIT
164+
: OWNERSHIP_FORMAT_VERSION_32BIT;
165+
#else
166+
// OSS builds always use 32-bit format for now
167+
uint32_t format_to_use = OWNERSHIP_FORMAT_VERSION_32BIT;
168+
#endif
169+
ownership_format_version = static_cast<uint32_t>(initAdminValue(
170+
container_,
171+
AdminId::OWNERSHIP_FORMAT_VERSION,
172+
static_cast<uint64_t>(format_to_use),
173+
true, // write
174+
[] {}));
175+
} else {
176+
// Existing DB: read format version, default to 32-bit if not present
177+
ownership_format_version = static_cast<uint32_t>(initAdminValue(
178+
container_,
179+
AdminId::OWNERSHIP_FORMAT_VERSION,
180+
static_cast<uint64_t>(OWNERSHIP_FORMAT_VERSION_32BIT),
181+
false, // don't write
182+
[] {}));
183+
}
160184

161185
VLOG(1) << folly::sformat(
162186
"ownership_format_version: {} ({})",

glean/rocksdb/ownership.cpp

Lines changed: 99 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <cpp/memory.h> // @manual
1111
#else
1212
#include "common/hs/util/cpp/memory.h"
13+
#include "justknobs/JustKnobProxy.h"
1314
#endif
1415
#include <glean/rts/ownership/uset.h>
1516
#include "glean/rocksdb/database-impl.h"
@@ -73,6 +74,17 @@ DatabaseImpl::loadOwnershipDerivedCounters() {
7374

7475
namespace {
7576

77+
// Helper to serialize UnitId/UsetId based on format version
78+
rocksdb::Slice
79+
toSliceForFormat(binary::Output& out, uint64_t id, uint32_t format_version) {
80+
if (format_version == OWNERSHIP_FORMAT_VERSION_32BIT) {
81+
out.fixed(static_cast<uint32_t>(id));
82+
} else {
83+
out.fixed(id);
84+
}
85+
return slice(out);
86+
}
87+
7688
void putOwnerSet(
7789
ContainerImpl& container,
7890
rocksdb::WriteBatch& batch,
@@ -272,10 +284,12 @@ void DatabaseImpl::addOwnership(const std::vector<OwnershipSet>& ownership) {
272284
touched.push_back(unit_id);
273285
} else {
274286
unit_id = first_unit_id + ownership_unit_counters.size() + new_count;
287+
// Write UnitId in format based on ownership_format_version
288+
binary::Output unitIdOut;
275289
check(batch.Put(
276290
container_.family(Family::ownershipUnits),
277291
slice(set.unit),
278-
toSlice(unit_id)));
292+
toSliceForFormat(unitIdOut, unit_id, ownership_format_version)));
279293
EncodedNat key(unit_id);
280294
check(batch.Put(
281295
container_.family(Family::ownershipUnitIds),
@@ -907,6 +921,17 @@ std::optional<UsetId> DatabaseImpl::FactOwnerCache::getOwner(
907921
}
908922

909923
void DatabaseImpl::FactOwnerCache::prepare(ContainerImpl& container) {
924+
// Static function - need to check gatekeeper for format
925+
#ifndef OSS
926+
static facebook::jk::BooleanKnob use64BitOwnership(
927+
"glean/ownership:64_bit_ids");
928+
uint32_t format_version = use64BitOwnership()
929+
? OWNERSHIP_FORMAT_VERSION_64BIT
930+
: OWNERSHIP_FORMAT_VERSION_32BIT;
931+
#else
932+
uint32_t format_version = OWNERSHIP_FORMAT_VERSION_32BIT;
933+
#endif
934+
910935
auto t = makeAutoTimer("prepareFactOwnerCache");
911936

912937
std::unique_ptr<rocksdb::Iterator> iter(container.db->NewIterator(
@@ -934,7 +959,18 @@ void DatabaseImpl::FactOwnerCache::prepare(ContainerImpl& container) {
934959
index.push_back(HAS_PAGE);
935960
binary::Output out;
936961
out.bytes(ids.data(), ids.size() * sizeof(uint16_t));
937-
out.bytes(sets.data(), sets.size() * sizeof(UsetId));
962+
// Write UsetIds in format based on format_version
963+
if (format_version == OWNERSHIP_FORMAT_VERSION_32BIT) {
964+
// Write 32-bit UsetIds
965+
std::vector<uint32_t> sets32(sets.size());
966+
for (size_t i = 0; i < sets.size(); i++) {
967+
sets32[i] = static_cast<uint32_t>(sets[i]);
968+
}
969+
out.bytes(sets32.data(), sets32.size() * sizeof(uint32_t));
970+
} else {
971+
// Write 64-bit UsetIds
972+
out.bytes(sets.data(), sets.size() * sizeof(UsetId));
973+
}
938974
batch.Put(
939975
container.family(Family::factOwnerPages),
940976
toSlice(prefix),
@@ -980,19 +1016,39 @@ void DatabaseImpl::FactOwnerCache::prepare(ContainerImpl& container) {
9801016
// write the last page
9811017
writePage();
9821018

983-
batch.Put(
984-
container.family(Family::factOwnerPages),
985-
INDEX_KEY,
986-
slice(
987-
folly::ByteRange(
988-
reinterpret_cast<const uint8_t*>(index.data()),
989-
index.size() * sizeof(UsetId))));
1019+
// Write index in format based on format_version
1020+
if (format_version == OWNERSHIP_FORMAT_VERSION_32BIT) {
1021+
// Write 32-bit index entries
1022+
std::vector<uint32_t> index32(index.size());
1023+
if (!index.empty()) {
1024+
for (size_t i = 0; i < index.size(); i++) {
1025+
index32[i] = static_cast<uint32_t>(index[i]);
1026+
}
1027+
}
1028+
batch.Put(
1029+
container.family(Family::factOwnerPages),
1030+
INDEX_KEY,
1031+
slice(
1032+
folly::ByteRange(
1033+
reinterpret_cast<const uint8_t*>(index32.data()),
1034+
index32.size() * sizeof(uint32_t))));
1035+
} else {
1036+
// Write 64-bit index entries
1037+
batch.Put(
1038+
container.family(Family::factOwnerPages),
1039+
INDEX_KEY,
1040+
slice(
1041+
folly::ByteRange(
1042+
reinterpret_cast<const uint8_t*>(index.data()),
1043+
index.size() * sizeof(UsetId))));
1044+
}
9901045

9911046
t.logFormat(
992-
"{} index entries, {} populated, {} orphans",
1047+
"{} index entries, {} populated, {} orphans (format: {})",
9931048
index.size(),
9941049
populated,
995-
orphaned);
1050+
orphaned,
1051+
format_version == OWNERSHIP_FORMAT_VERSION_32BIT ? "32-bit" : "64-bit");
9961052

9971053
// record the number of orphaned facts, this will be fetched by ownershipStats
9981054
batch.Put(
@@ -1110,16 +1166,38 @@ void DatabaseImpl::addDefineOwnership(DefineOwnership& def) {
11101166
pred.new_ids_.size() *
11111167
sizeof(std::remove_reference<
11121168
decltype(pred.new_ids_)>::type::value_type));
1113-
val.bytes(
1114-
pred.owners_.data(),
1115-
pred.owners_.size() *
1116-
sizeof(std::remove_reference<
1117-
decltype(pred.owners_)>::type::value_type));
1118-
val.bytes(
1119-
pred.new_owners_.data(),
1120-
pred.new_owners_.size() *
1121-
sizeof(std::remove_reference<
1122-
decltype(pred.new_owners_)>::type::value_type));
1169+
1170+
// Write owners in format based on ownership_format_version
1171+
if (ownership_format_version == OWNERSHIP_FORMAT_VERSION_32BIT) {
1172+
// 32-bit UsetId format
1173+
std::vector<uint32_t> owners32(pred.owners_.size());
1174+
if (!pred.owners_.empty()) {
1175+
for (size_t i = 0; i < pred.owners_.size(); i++) {
1176+
owners32[i] = static_cast<uint32_t>(pred.owners_[i]);
1177+
}
1178+
}
1179+
val.bytes(owners32.data(), owners32.size() * sizeof(uint32_t));
1180+
1181+
std::vector<uint32_t> new_owners32(pred.new_owners_.size());
1182+
if (!pred.new_owners_.empty()) {
1183+
for (size_t i = 0; i < pred.new_owners_.size(); i++) {
1184+
new_owners32[i] = static_cast<uint32_t>(pred.new_owners_[i]);
1185+
}
1186+
}
1187+
val.bytes(new_owners32.data(), new_owners32.size() * sizeof(uint32_t));
1188+
} else {
1189+
// 64-bit UsetId format
1190+
val.bytes(
1191+
pred.owners_.data(),
1192+
pred.owners_.size() *
1193+
sizeof(std::remove_reference<
1194+
decltype(pred.owners_)>::type::value_type));
1195+
val.bytes(
1196+
pred.new_owners_.data(),
1197+
pred.new_owners_.size() *
1198+
sizeof(std::remove_reference<
1199+
decltype(pred.new_owners_)>::type::value_type));
1200+
}
11231201

11241202
check(batch.Put(
11251203
container_.family(Family::ownershipDerivedRaw),

0 commit comments

Comments
 (0)