From bf97c3dbcee70efb24acf6d20c0405ce1cce1607 Mon Sep 17 00:00:00 2001 From: Josh Slocum Date: Wed, 22 Feb 2023 10:52:26 -0600 Subject: [PATCH] adding java tenant blob management test and fixing bug it found (#9428) --- .../BlobGranuleIntegrationTest.java | 78 +++++++++++++++++++ fdbclient/NativeAPI.actor.cpp | 12 +-- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/bindings/java/src/integration/com/apple/foundationdb/BlobGranuleIntegrationTest.java b/bindings/java/src/integration/com/apple/foundationdb/BlobGranuleIntegrationTest.java index 170b138def..2948891a27 100644 --- a/bindings/java/src/integration/com/apple/foundationdb/BlobGranuleIntegrationTest.java +++ b/bindings/java/src/integration/com/apple/foundationdb/BlobGranuleIntegrationTest.java @@ -117,4 +117,82 @@ class BlobGranuleIntegrationTest { System.out.println("Blob granule management tests complete!"); } } + + @Test + void blobManagementFunctionsTenantTest() throws Exception { + /* + * A test that runs a blob range through the lifecycle of blob management. + * Identical to the above test, but everything is scoped to a tenant instead of a database + */ + Random rand = new Random(); + byte[] key = new byte[16]; + byte[] value = new byte[8]; + + rand.nextBytes(key); + key[0] = (byte)0x30; + rand.nextBytes(value); + + Range blobRange = Range.startsWith(key); + byte[] tenantName = "BGManagementTenant".getBytes(); + try (Database db = fdb.open()) { + TenantManagement.createTenant(db, tenantName).join(); + + System.out.println("Created tenant for test"); + + try (Tenant tenant = db.openTenant(tenantName)) { + System.out.println("Opened tenant for test"); + + boolean blobbifySuccess = tenant.blobbifyRangeBlocking(blobRange.begin, blobRange.end).join(); + Assertions.assertTrue(blobbifySuccess); + + Long verifyVersion = tenant.verifyBlobRange(blobRange.begin, blobRange.end).join(); + + Assertions.assertTrue(verifyVersion >= 0); + + // list blob ranges + KeyRangeArrayResult blobRanges = tenant.listBlobbifiedRanges(blobRange.begin, blobRange.end, 2).join(); + Assertions.assertEquals(1, blobRanges.getKeyRanges().size()); + Assertions.assertArrayEquals(blobRange.begin, blobRanges.getKeyRanges().get(0).begin); + Assertions.assertArrayEquals(blobRange.end, blobRanges.getKeyRanges().get(0).end); + + boolean flushSuccess = tenant.flushBlobRange(blobRange.begin, blobRange.end, false).join(); + Assertions.assertTrue(flushSuccess); + + // verify after flush + Long verifyVersionAfterFlush = tenant.verifyBlobRange(blobRange.begin, blobRange.end).join(); + Assertions.assertTrue(verifyVersionAfterFlush >= 0); + Assertions.assertTrue(verifyVersionAfterFlush >= verifyVersion); + + boolean compactSuccess = tenant.flushBlobRange(blobRange.begin, blobRange.end, true).join(); + Assertions.assertTrue(compactSuccess); + + Long verifyVersionAfterCompact = tenant.verifyBlobRange(blobRange.begin, blobRange.end).join(); + Assertions.assertTrue(verifyVersionAfterCompact >= 0); + Assertions.assertTrue(verifyVersionAfterCompact >= verifyVersionAfterFlush); + + // purge/wait + byte[] purgeKey = tenant.purgeBlobGranules(blobRange.begin, blobRange.end, -2, false).join(); + db.waitPurgeGranulesComplete(purgeKey).join(); + + // verify again + Long verifyVersionAfterPurge = tenant.verifyBlobRange(blobRange.begin, blobRange.end).join(); + Assertions.assertTrue(verifyVersionAfterPurge >= 0); + Assertions.assertTrue(verifyVersionAfterPurge >= verifyVersionAfterCompact); + + // force purge/wait + byte[] forcePurgeKey = tenant.purgeBlobGranules(blobRange.begin, blobRange.end, -2, true).join(); + tenant.waitPurgeGranulesComplete(forcePurgeKey).join(); + + // check verify fails + Long verifyVersionLast = tenant.verifyBlobRange(blobRange.begin, blobRange.end).join(); + Assertions.assertEquals(-1, verifyVersionLast); + + // unblobbify + boolean unblobbifySuccess = tenant.unblobbifyRange(blobRange.begin, blobRange.end).join(); + Assertions.assertTrue(unblobbifySuccess); + + System.out.println("Blob granule management tenant tests complete!"); + } + } + } } diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index 1eec67ade5..75c56fc265 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -10876,13 +10876,13 @@ ACTOR Future purgeBlobGranulesActor(Reference db, if ((!blobbifiedBegin.get().empty() && blobbifiedBegin.get().front().begin < purgeRange.begin) || (!blobbifiedEnd.get().empty() && blobbifiedEnd.get().front().begin < purgeRange.end)) { TraceEvent("UnalignedPurge") - .detail("Range", range) + .detail("Range", purgeRange) .detail("Version", purgeVersion) .detail("Force", force); throw unsupported_operation(); } - Value purgeValue = blobGranulePurgeValueFor(purgeVersion, range, force); + Value purgeValue = blobGranulePurgeValueFor(purgeVersion, purgeRange, force); tr.atomicOp( addVersionStampAtEnd(blobGranulePurgeKeys.begin), purgeValue, MutationRef::SetVersionstampedKey); tr.set(blobGranulePurgeChangeKey, deterministicRandom()->randomUniqueID().toString()); @@ -10892,8 +10892,8 @@ ACTOR Future purgeBlobGranulesActor(Reference db, purgeKey = blobGranulePurgeKeys.begin.withSuffix(vs); if (BG_REQUEST_DEBUG) { fmt::print("purgeBlobGranules for range [{0} - {1}) at version {2} registered {3}\n", - range.begin.printable(), - range.end.printable(), + purgeRange.begin.printable(), + purgeRange.end.printable(), purgeVersion, purgeKey.printable()); } @@ -10901,8 +10901,8 @@ ACTOR Future purgeBlobGranulesActor(Reference db, } catch (Error& e) { if (BG_REQUEST_DEBUG) { fmt::print("purgeBlobGranules for range [{0} - {1}) at version {2} encountered error {3}\n", - range.begin.printable(), - range.end.printable(), + purgeRange.begin.printable(), + purgeRange.end.printable(), purgeVersion, e.name()); }