@Override public Optional<ValueAndBound<T2>> getLastKnownLocalValue() { return delegate.getLastKnownLocalValue() .map(preservingBounds(transformFromUnderlying)); }
@Override public Optional<ValueAndBound<T2>> getValueForTimestamp(long timestamp) { return delegate.getValueForTimestamp(timestamp) .map(preservingBounds(transformFromUnderlying)); }
private CheckAndSetResult<ValueAndBound<InternalSchemaMetadata>> tryPerpetuateExistingState() { return coordinationService.tryTransformCurrentValue(valueAndBound -> valueAndBound.value().orElseGet(InternalSchemaMetadata::defaultValue)); }
@Test public void successfulUpdateUpdatesCache() { when(coordinationStore.transformAgreedValue(any())).thenReturn( CheckAndSetResult.of(true, ImmutableList.of(STRING_AND_ONE_HUNDRED))); stringCoordinationService.tryTransformCurrentValue(unused -> STRING); stringCoordinationService.getValueForTimestamp(56); stringCoordinationService.getValueForTimestamp(88); verify(coordinationStore, never()).getAgreedValue(); }
@Test public void retrieveLocalValueRetrievesCachedValue() { when(coordinationStore.getAgreedValue()).thenReturn(Optional.of(STRING_AND_ONE_HUNDRED)); assertThat(stringCoordinationService.getValueForTimestamp(42)).contains(STRING_AND_ONE_HUNDRED); when(coordinationStore.getAgreedValue()).thenReturn(Optional.of(OTHER_STRING_AND_ONE_THOUSAND)); assertThat(stringCoordinationService.getLastKnownLocalValue()).contains(STRING_AND_ONE_HUNDRED); verify(coordinationStore, times(1)).getAgreedValue(); }
@Test public void failedUpdateUpdatesCache() { when(coordinationStore.transformAgreedValue(any())).thenReturn( CheckAndSetResult.of(false, ImmutableList.of(STRING_AND_ONE_HUNDRED))); stringCoordinationService.tryTransformCurrentValue(unused -> STRING); stringCoordinationService.getValueForTimestamp(56); stringCoordinationService.getValueForTimestamp(88); verify(coordinationStore, never()).getAgreedValue(); }
@Test public void getsEmptyLocalValueFromDelegateIfDelegateHasEmptyLocalValue() { when(delegate.getLastKnownLocalValue()).thenReturn(Optional.empty()); assertThat(coordinationService.getLastKnownLocalValue()).isEmpty(); verify(delegate).getLastKnownLocalValue(); } }
@Test public void getsEmptyFromDelegateIfEmpty() { when(delegate.getValueForTimestamp(anyLong())).thenReturn(Optional.empty()); assertThat(coordinationService.getValueForTimestamp(BOUND)).isEmpty(); verify(delegate).getValueForTimestamp(BOUND); }
@Override public CheckAndSetResult<ValueAndBound<T2>> tryTransformCurrentValue(Function<ValueAndBound<T2>, T2> valueUpdater) { CheckAndSetResult<ValueAndBound<T1>> delegateResult = delegate.tryTransformCurrentValue( preservingBounds(transformFromUnderlying).andThen(valueUpdater).andThen(transformToUnderlying)); return CheckAndSetResult.of( delegateResult.successful(), delegateResult.existingValues() .stream() .map(preservingBounds(transformFromUnderlying)) .collect(Collectors.toList())); }
/** * Registers a gauge which tracks the current value of the validity bound. Under normal operation and within the * lifetiem of a single JVM, this should not decrease. * * @param metricsManager metrics manager to register the gauge on * @param metadataCoordinationService metadata coordination service that should be tracked */ private static void registerValidityBoundMetric(MetricsManager metricsManager, CoordinationService<InternalSchemaMetadata> metadataCoordinationService) { metricsManager.registerMetric( MetadataCoordinationServiceMetrics.class, AtlasDbMetricNames.COORDINATION_LAST_VALID_BOUND, TrackerUtils.createCachingExceptionHandlingGauge( log, Clock.defaultClock(), AtlasDbMetricNames.COORDINATION_LAST_VALID_BOUND, () -> metadataCoordinationService.getLastKnownLocalValue() .map(ValueAndBound::bound) .orElse(Long.MIN_VALUE))); }
public Integer getTransactionsSchemaVersion(long timestamp) { if (timestamp < AtlasDbConstants.STARTING_TS) { throw new SafeIllegalStateException("Query attempted for timestamp {} which was never given out by the" + " timestamp service, as timestamps start at {}", SafeArg.of("queriedTimestamp", timestamp), SafeArg.of("startOfTime", AtlasDbConstants.STARTING_TS)); } Optional<Integer> possibleVersion = extractTimestampVersion(coordinationService.getValueForTimestamp(timestamp), timestamp); return possibleVersion.orElse(null); }
/** * Attempts to install a new transactions table schema version, by submitting a relevant transform. * * The execution of this method does not guarantee that the provided version will eventually be installed. * This method returns true if and only if in the map agreed by the coordination service evaluated at the validity * bound, the transactions schema version is equal to newVersion. */ public boolean tryInstallNewTransactionsSchemaVersion(int newVersion) { List<Integer> presentVersionPeakValidity = coordinationService.tryTransformCurrentValue( valueAndBound -> installNewVersionInMapOrDefault(newVersion, valueAndBound)) .existingValues() .stream() .map(valueAndBound -> valueAndBound.value() .orElseThrow(() -> new SafeIllegalStateException("Unexpectedly found no value in store")) .timestampToTransactionsTableSchemaVersion() .getValueForTimestamp(valueAndBound.bound())) .collect(Collectors.toList()); return Iterables.getOnlyElement(presentVersionPeakValidity) == newVersion; }
/** * Registers a gauge which tracks the eventual transactions schema version - that is, at the end of the current * period of validity for the bound, what the metadata says the transactions schema version should be. * * @param metricsManager metrics manager to register the gauge on * @param metadataCoordinationService metadata coordination service that should be tracked */ private static void registerEventualTransactionsSchemaVersionMetric(MetricsManager metricsManager, CoordinationService<InternalSchemaMetadata> metadataCoordinationService) { metricsManager.registerMetric( MetadataCoordinationServiceMetrics.class, AtlasDbMetricNames.COORDINATION_EVENTUAL_TRANSACTIONS_SCHEMA_VERSION, TrackerUtils.createCachingExceptionHandlingGauge( log, Clock.defaultClock(), AtlasDbMetricNames.COORDINATION_EVENTUAL_TRANSACTIONS_SCHEMA_VERSION, () -> { Optional<ValueAndBound<InternalSchemaMetadata>> latestValue = metadataCoordinationService.getLastKnownLocalValue(); return latestValue .map(ValueAndBound::value) .flatMap(Function.identity()) .map(InternalSchemaMetadata::timestampToTransactionsTableSchemaVersion) .map(timestampMap -> timestampMap.getValueForTimestamp(latestValue.get().bound())) .orElse(null); })); }
@Test public void getsValueFromDelegateIfPresent() { when(delegate.getValueForTimestamp(anyLong())).thenReturn(Optional.of(ValueAndBound.of(INTEGER_1, BOUND))); assertThat(coordinationService.getValueForTimestamp(BOUND)).contains(ValueAndBound.of(STRING_1, BOUND)); verify(delegate).getValueForTimestamp(BOUND); verify(intToStringTransform).apply(INTEGER_1); }
@Test public void checkAndSetFailureCase() { when(delegate.tryTransformCurrentValue(any())).thenReturn( CheckAndSetResult.of(false, ImmutableList.of(ValueAndBound.of(INTEGER_1, BOUND)))); CheckAndSetResult<ValueAndBound<String>> casResult = coordinationService.tryTransformCurrentValue(DUMMY_TRANSFORMATION); assertThat(casResult.successful()).isFalse(); assertThat(casResult.existingValues()).containsExactly(ValueAndBound.of(STRING_1, BOUND)); verify(delegate).tryTransformCurrentValue(any()); }
@Test public void getsLastKnownLocalValueFromDelegateIfPresent() { when(delegate.getLastKnownLocalValue()).thenReturn(Optional.of(ValueAndBound.of(INTEGER_1, BOUND))); assertThat(coordinationService.getLastKnownLocalValue()).contains(ValueAndBound.of(STRING_1, BOUND)); verify(delegate).getLastKnownLocalValue(); verify(intToStringTransform).apply(INTEGER_1); }
@Test public void canLookUpNewValueIfCacheOutOfDate() { when(coordinationStore.getAgreedValue()).thenReturn(Optional.of(STRING_AND_ONE_HUNDRED)); assertThat(stringCoordinationService.getValueForTimestamp(42)).contains(STRING_AND_ONE_HUNDRED); assertThat(stringCoordinationService.getValueForTimestamp(742)).isEmpty(); when(coordinationStore.getAgreedValue()).thenReturn(Optional.of(OTHER_STRING_AND_ONE_THOUSAND)); assertThat(stringCoordinationService.getValueForTimestamp(742)).contains(OTHER_STRING_AND_ONE_THOUSAND); }
@Test public void checkAndSetSuccessfulCase() { when(delegate.tryTransformCurrentValue(any())).thenReturn( CheckAndSetResult.of(true, ImmutableList.of(ValueAndBound.of(INTEGER_1, BOUND)))); CheckAndSetResult<ValueAndBound<String>> casResult = coordinationService.tryTransformCurrentValue(DUMMY_TRANSFORMATION); assertThat(casResult.successful()).isTrue(); assertThat(casResult.existingValues()).containsExactly(ValueAndBound.of(STRING_1, BOUND)); verify(delegate).tryTransformCurrentValue(any()); }
@Test public void returnsValidityBoundFromCoordinationService() { Gauge<Long> boundGauge = getGauge(metricsManager, AtlasDbMetricNames.COORDINATION_LAST_VALID_BOUND); assertThat(boundGauge.getValue()).isEqualTo(TIMESTAMP_1); verify(metadataCoordinationService).getLastKnownLocalValue(); verifyNoMoreInteractions(metadataCoordinationService); }
@Test public void canCacheValues() { when(coordinationStore.getAgreedValue()).thenReturn(Optional.of(STRING_AND_ONE_HUNDRED)); assertThat(stringCoordinationService.getValueForTimestamp(42)).contains(STRING_AND_ONE_HUNDRED); assertThat(stringCoordinationService.getValueForTimestamp(42)).contains(STRING_AND_ONE_HUNDRED); assertThat(stringCoordinationService.getValueForTimestamp(42)).contains(STRING_AND_ONE_HUNDRED); verify(coordinationStore, times(1)).getAgreedValue(); }