@Override public TimestampStoreInvalidator createTimestampStoreInvalidator(KeyValueService rawKvs) { return CassandraTimestampStoreInvalidator.create(rawKvs); } }
public static CassandraTimestampStoreInvalidator create(KeyValueService keyValueService) { Preconditions.checkArgument(keyValueService instanceof CassandraKeyValueService, "CassandraTimestampStoreInvalidator should be instantiated with a CassandraKeyValueService!"); CassandraKeyValueService cassandraKeyValueService = (CassandraKeyValueService) keyValueService; return new CassandraTimestampStoreInvalidator(new CassandraTimestampBackupRunner(cassandraKeyValueService)); }
@Test public void canBackupTwice() { assertThat(invalidator.backupAndInvalidate()).isEqualTo(CassandraTimestampUtils.INITIAL_VALUE); assertThat(invalidator.backupAndInvalidate()).isEqualTo(CassandraTimestampUtils.INITIAL_VALUE); }
/** * 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. }
@Test public void multipleInvalidatorsForSameKeyValueServiceAllReturnSameResults() { long limit = getBoundAfterTakingOutOneMillionTimestamps(); CassandraTestTools.executeInParallelOnExecutorService(() -> assertThat(CassandraTimestampStoreInvalidator.create(kv).backupAndInvalidate()).isEqualTo(limit)); }
@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); }
@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 throwsIfCreatingWithNonCassandraKvs() { assertThatThrownBy(() -> CassandraTimestampStoreInvalidator.create(new InMemoryKeyValueService(false))) .isInstanceOf(IllegalArgumentException.class); }
@Test public void canBackupTimestampTableIfItExistsWithNoData() { assertThat(invalidator.backupAndInvalidate()).isEqualTo(CassandraTimestampUtils.INITIAL_VALUE); }
@Test public void restoringTimestampTableWithNoDataIsANoOp() { invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
public static CassandraTimestampStoreInvalidator create(KeyValueService keyValueService) { Preconditions.checkArgument(keyValueService instanceof CassandraKeyValueService, "CassandraTimestampStoreInvalidator should be instantiated with a CassandraKeyValueService!"); CassandraKeyValueService cassandraKeyValueService = (CassandraKeyValueService) keyValueService; return new CassandraTimestampStoreInvalidator(new CassandraTimestampBackupRunner(cassandraKeyValueService)); }
@Override public TimestampStoreInvalidator createTimestampStoreInvalidator(KeyValueService rawKvs) { return CassandraTimestampStoreInvalidator.create(rawKvs); } }
@Test public void backupReturnsTimestampFromBackupRunner() { assertThat(invalidator.backupAndInvalidate()).isEqualTo(BACKUP_TIMESTAMP); verify(backupRunner, times(1)).backupExistingTimestamp(); }
@Test public void restoringValidTimestampTableIsANoOp() { assertWeCanReadInitialValue(); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
@Test public void canBackupTimestampTableIfItExistsWithData() { long limit = getBoundAfterTakingOutOneMillionTimestamps(); assertThat(invalidator.backupAndInvalidate()).isEqualTo(limit); }
@Test public void restoringTimestampTableIfItDoesNotExistIsANoOp() { kv.dropTable(AtlasDbConstants.TIMESTAMP_TABLE); invalidator.revalidateFromBackup(); assertWeCanReadInitialValue(); }
@Test public void canBackupTimestampTableIfItDoesNotExist() { kv.dropTable(AtlasDbConstants.TIMESTAMP_TABLE); assertThat(invalidator.backupAndInvalidate()).isEqualTo(CassandraTimestampUtils.INITIAL_VALUE); }
@Test public void ensuresTablesExistOnInvalidate() { invalidator.backupAndInvalidate(); verify(backupRunner, times(1)).ensureTimestampTableExists(); }