@Test public void revalidateCallsRestoreOnBackupRunner() { invalidator.revalidateFromBackup(); verify(backupRunner, times(1)).restoreFromBackup(); } }
@Test public void ensuresTablesExistOnRevalidate() { invalidator.revalidateFromBackup(); verify(backupRunner, times(1)).ensureTimestampTableExists(); }
@Test public void restoringValidTimestampTableIsANoOp() { assertWeCanReadInitialValue(); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
@Test public void restoringTimestampTableWithNoDataIsANoOp() { invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
@Test public void restoringTimestampTableIfItDoesNotExistIsANoOp() { kv.dropTable(AtlasDbConstants.TIMESTAMP_TABLE); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
@Test public void canBackupAndRestoreTimestampTable() { TimestampBoundStore timestampBoundStore = CassandraTimestampBoundStore.create(kv); long limit = timestampBoundStore.getUpperLimit(); timestampBoundStore.storeUpperLimit(limit + ONE_MILLION); invalidator.backupAndInvalidate(); invalidator.revalidateFromBackup(); assertThat(timestampBoundStore.getUpperLimit()).isEqualTo(limit + ONE_MILLION); }
/** * Consistent results here mean that: * (1) all calls to backupAndInvalidate() return the same value V, and * (2) this value V is the maximum of all successfully stored timestamp bounds. */ @Test public void invalidationDuringTimestampIssuanceYieldsConsistentResults() { Set<Long> backedUpValues = Sets.newConcurrentHashSet(); AtomicLong maxSuccessfulBound = new AtomicLong(CassandraTimestampUtils.INITIAL_VALUE); CassandraTestTools.executeInParallelOnExecutorService(() -> { CassandraTimestampStoreInvalidator storeInvalidator = CassandraTimestampStoreInvalidator.create(kv); try { if (ThreadLocalRandom.current().nextBoolean()) { backedUpValues.add(storeInvalidator.backupAndInvalidate()); } else { maxSuccessfulBound.accumulateAndGet(getBoundAfterTakingOutOneMillionTimestamps(), Math::max); } } catch (IllegalArgumentException | IllegalStateException | MultipleRunningTimestampServiceError error) { // Can arise if trying to manipulate the timestamp bound during/after an invalidation. This is fine. } }); if (!backedUpValues.isEmpty()) { invalidator.revalidateFromBackup(); assertThat(Iterables.getOnlyElement(backedUpValues)).isEqualTo(maxSuccessfulBound.get()); assertWeCanReadTimestamp(maxSuccessfulBound.get()); } // 2^-32 chance that nothing got backed up; accept in this case. }