echonesis commented on code in PR #11841:
URL: https://github.com/apache/ozone/pull/11841#discussion_r4438408844
##########
hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/TestSnapshotDiffManager.java:
##########
@@ -368,19 +373,118 @@ public void init() throws RocksDBException, IOException,
ExecutionException {
SnapshotCache snapshotCache = new SnapshotCache(mockCacheLoader(), 10,
omMetrics, 0, true,
new OmReadOnlyLock());
- when(omSnapshotManager.getActiveSnapshot(anyString(), anyString(),
anyString()))
- .thenAnswer(invocationOnMock -> {
- SnapshotInfo snapInfo = SnapshotUtils.getSnapshotInfo(ozoneManager,
invocationOnMock.getArgument(0),
- invocationOnMock.getArgument(1),
invocationOnMock.getArgument(2));
- return snapshotCache.get(snapInfo.getSnapshotId());
- });
+ HddsWhiteboxTestUtils.setInternalState(omSnapshotManager, "ozoneManager",
ozoneManager);
+ HddsWhiteboxTestUtils.setInternalState(omSnapshotManager, "snapshotCache",
snapshotCache);
+ Mockito.doCallRealMethod().when(omSnapshotManager)
+ .getActiveSnapshot(anyString(), anyString(), anyString(),
any(UUID.class));
when(ozoneManager.getOmSnapshotManager()).thenReturn(omSnapshotManager);
snapshotDiffManager = new SnapshotDiffManager(db, ozoneManager,
snapDiffJobTable, snapDiffReportTable, snapDiffPurgedJobTable,
columnFamilyOptions, codecRegistry);
when(omSnapshotManager.getDiffCleanupServiceInterval()).thenReturn(0L);
}
+ @ParameterizedTest
+ @CsvSource({"0, false, false", "1, false, false", "2, false, false", "3,
false, false",
+ "3, true, false", "0, false, true", "1, false, true", "2, false, true",
"3, false, true", "3, true, true"})
+ public void testSnapshotDiffLocks(int failOnOpen, boolean sameSnapshot,
boolean optimized) throws Exception {
+ SnapshotInfo from = snapshotInfo;
+ SnapshotInfo to = sameSnapshot ? from : snapshotInfoList.get(0);
+ OzoneManagerLock lock = new OzoneManagerLock(new OzoneConfiguration());
+ when(omMetadataManager.getLock()).thenReturn(lock);
+ try (SnapshotCache cache = new SnapshotCache(mockCacheLoader(), 10,
ozoneManager.getMetrics(), 0, true, lock)) {
+ SnapshotDiffManager manager =
spy(newSnapshotDiffManagerWithOptimizedEnabled(optimized));
+ doReturn(failOnOpen != 0,
false).when(manager).areDiffJobAndSnapshotsActive(
+ VOLUME_NAME, BUCKET_NAME, from.getName(), to.getName());
+ AtomicInteger opens = new AtomicInteger();
+ OmSnapshotManager omSnapshotManager =
ozoneManager.getOmSnapshotManager();
+ doAnswer(invocation -> {
+ // Both stripes must be held before even the first snapshot is opened.
+ assertTrue(lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
from.getSnapshotId().toString()) > 0);
+ assertTrue(lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
to.getSnapshotId().toString()) > 0);
+ if (opens.incrementAndGet() == failOnOpen) {
+ throw new IOException("Snapshot load failed");
+ }
+ String name = invocation.getArgument(2);
+ return cache.get(name.equals(from.getName()) ? from.getSnapshotId() :
to.getSnapshotId());
+ }).when(omSnapshotManager).getActiveSnapshot(anyString(), anyString(),
anyString(), any(UUID.class));
+ String jobKey = generateSnapDiffJobKey.apply(from, to);
+ String jobId = UUID.randomUUID().toString();
+ manager.getSnapDiffJobTable().put(jobKey, new
SnapshotDiffJob(System.currentTimeMillis(), jobId,
+ IN_PROGRESS, VOLUME_NAME, BUCKET_NAME, from.getName(), to.getName(),
false, false, 0, null, 0.0, ""));
+ if (failOnOpen == 1 || failOnOpen == 2) {
+ RuntimeException failure = assertThrows(RuntimeException.class, () ->
manager.generateSnapshotDiffReport(
+ jobKey, jobId, VOLUME_NAME, BUCKET_NAME, from.getName(),
to.getName(), true, false, false));
+ assertEquals("Snapshot load failed", failure.getCause().getMessage());
+ assertEquals(FAILED,
manager.getSnapDiffJobTable().get(jobKey).getStatus());
+ } else {
+ manager.generateSnapshotDiffReport(jobKey, jobId, VOLUME_NAME,
BUCKET_NAME,
+ from.getName(), to.getName(), true, false, false);
+ }
+ assertEquals(failOnOpen == 0 ? 0 : Math.min(failOnOpen, 2), opens.get());
+ assertEquals(0, lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
from.getSnapshotId().toString()));
+ assertEquals(0, lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
to.getSnapshotId().toString()));
+ assertEquals(0, cache.totalRefCount(from.getSnapshotId()));
+ assertEquals(0, cache.totalRefCount(to.getSnapshotId()));
+ }
+ }
+
+ @ParameterizedTest
+ @org.junit.jupiter.params.provider.ValueSource(ints = {1, 2})
+ public void testSnapshotDiffLocksAfterSnapshotNameReuse(int replaceOnOpen)
throws Exception {
+ SnapshotInfo from = snapshotInfo;
+ SnapshotInfo to = snapshotInfoList.get(0);
+ OzoneManagerLock lock = new OzoneManagerLock(new OzoneConfiguration());
+ when(omMetadataManager.getLock()).thenReturn(lock);
+ try (SnapshotCache cache = new SnapshotCache(mockCacheLoader(), 10,
ozoneManager.getMetrics(), 0, true, lock)) {
+ SnapshotDiffManager manager = spy(snapshotDiffManager);
+ doReturn(true, false).when(manager).areDiffJobAndSnapshotsActive(
+ VOLUME_NAME, BUCKET_NAME, from.getName(), to.getName());
+ Set<UUID> openedIds = new LinkedHashSet<>();
+ Set<UUID> replacementIds = new LinkedHashSet<>();
+ AtomicInteger opens = new AtomicInteger();
+ OmSnapshotManager omSnapshotManager =
ozoneManager.getOmSnapshotManager();
+ HddsWhiteboxTestUtils.setInternalState(omSnapshotManager,
"snapshotCache", cache);
+ doAnswer(invocation -> {
+ if (opens.incrementAndGet() == replaceOnOpen) {
+ assertTrue(lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
from.getSnapshotId().toString()) > 0);
+ assertTrue(lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
to.getSnapshotId().toString()) > 0);
+ UUID replacementId = LongStream.range(0, 1024).mapToObj(id -> new
UUID(0, id))
+ .filter(id -> lock.getReadHoldCount(SNAPSHOT_DB_LOCK,
id.toString()) == 0)
+ .findFirst().orElseThrow(() -> new AssertionError("No unheld
snapshot DB stripe found"));
+ // Simulate A being renamed away and C taking A's old name after A
and B were prelocked.
+ SnapshotInfo original = replaceOnOpen == 1 ? from : to;
+ SnapshotInfo replacement =
original.toBuilder().setSnapshotId(replacementId).build();
+ replacementIds.add(replacementId);
+
when(snapshotInfoTable.get(original.getTableKey())).thenReturn(replacement);
+ }
+ UUID id = invocation.getArgument(3);
+ assertTrue(lock.getReadHoldCount(SNAPSHOT_DB_LOCK, id.toString()) > 0);
+ Object handle = invocation.callRealMethod();
+ openedIds.add(id);
+ return handle;
+ }).when(omSnapshotManager).getActiveSnapshot(anyString(), anyString(),
anyString(), any(UUID.class));
+ String jobKey = generateSnapDiffJobKey.apply(from, to);
+ String jobId = UUID.randomUUID().toString();
+ manager.getSnapDiffJobTable().put(jobKey, new
SnapshotDiffJob(System.currentTimeMillis(), jobId,
+ IN_PROGRESS, VOLUME_NAME, BUCKET_NAME, from.getName(), to.getName(),
false, false, 0, null, 0.0, ""));
+
+ RuntimeException failure = assertThrows(RuntimeException.class, () ->
manager.generateSnapshotDiffReport(
+ jobKey, jobId, VOLUME_NAME, BUCKET_NAME, from.getName(),
to.getName(), true, false, false));
+ assertTrue(failure.getCause().getMessage().contains("Snapshot name
mapping changed"));
Review Comment:
Thanks, updated to
assertThat(failure).cause().hasMessageContaining("Snapshot name mapping
changed") as suggested.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]