use of io.pravega.segmentstore.contracts.tables.BadKeyVersionException in project pravega by pravega.
the class TableSegmentLayoutTestBase method conditionalUpdateCheck.
private void conditionalUpdateCheck(Map<BufferView, BufferView> expectedEntries, Collection<BufferView> nonExistentKeys, ContainerTableExtension ext) throws Exception {
for (val e : expectedEntries.entrySet()) {
val te = TableEntry.versioned(e.getKey(), e.getValue(), 1234L);
AssertExtensions.assertSuppliedFutureThrows("Expected the update to have failed with BadKeyVersionException.", () -> ext.put(SEGMENT_NAME, Collections.singletonList(te), TIMEOUT), ex -> ex instanceof BadKeyVersionException);
}
}
use of io.pravega.segmentstore.contracts.tables.BadKeyVersionException in project pravega by pravega.
the class TableBasedMetadataStoreMockTests method testBadKeyVersionExceptionDuringWrite.
@Test
public void testBadKeyVersionExceptionDuringWrite() {
TableStore mockTableStore = mock(TableStore.class);
@Cleanup TableBasedMetadataStore tableBasedMetadataStore = new TableBasedMetadataStore("test", mockTableStore, ChunkedSegmentStorageConfig.DEFAULT_CONFIG, executorService());
when(mockTableStore.createSegment(any(), any(), any())).thenReturn(Futures.failedFuture(new CompletionException(new StreamSegmentExistsException("test"))));
// Throw BadKeyVersionException exception
Exception e = new CompletionException(new BadKeyVersionException("test", new HashMap<>()));
val td = BaseMetadataStore.TransactionData.builder().key("foo").version(1L).dbObject(2L).build();
CompletableFuture<List<Long>> f = new CompletableFuture<>();
f.completeExceptionally(e);
when(mockTableStore.put(anyString(), any(), any())).thenReturn(f);
AssertExtensions.assertFutureThrows("write should throw an excpetion", tableBasedMetadataStore.writeAll(Collections.singleton(td)), ex -> ex instanceof StorageMetadataVersionMismatchException && ex.getCause() == e.getCause());
}
use of io.pravega.segmentstore.contracts.tables.BadKeyVersionException in project pravega by pravega.
the class TableMetadataStore method createSegment.
@Override
protected CompletableFuture<Void> createSegment(String segmentName, ArrayView segmentInfo, TimeoutTimer timer) {
ensureInitialized();
TableEntry entry = TableEntry.notExists(getTableKey(segmentName), segmentInfo);
return this.tableStore.put(this.metadataSegmentName, Collections.singletonList(entry), timer.getRemaining()).handle((ignored, ex) -> {
if (ex != null) {
if (Exceptions.unwrap(ex) instanceof BadKeyVersionException) {
ex = new StreamSegmentExistsException(segmentName);
}
throw new CompletionException(ex);
}
return null;
});
}
use of io.pravega.segmentstore.contracts.tables.BadKeyVersionException in project pravega by pravega.
the class ContainerKeyIndex method validateConditionalUpdateFailures.
private CompletableFuture<Void> validateConditionalUpdateFailures(DirectSegmentAccess segment, Map<TableKey, Long> expectedVersions, TimeoutTimer timer) {
assert !expectedVersions.isEmpty();
val bucketReader = TableBucketReader.key(segment, this::getBackpointerOffset, this.executor);
val searches = expectedVersions.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> findBucketEntry(segment, bucketReader, e.getKey().getKey(), e.getValue(), timer)));
return Futures.allOf(searches.values()).thenRun(() -> {
val failed = new HashMap<TableKey, Long>();
for (val e : searches.entrySet()) {
val actual = e.getValue().join();
boolean isValid = actual == null ? e.getKey().getVersion() == TableKey.NOT_EXISTS : e.getKey().getVersion() == actual.getVersion();
if (!isValid) {
failed.put(e.getKey(), actual == null ? TableKey.NOT_EXISTS : actual.getVersion());
}
}
if (!failed.isEmpty()) {
throw new CompletionException(new BadKeyVersionException(segment.getInfo().getName(), failed));
}
});
}
use of io.pravega.segmentstore.contracts.tables.BadKeyVersionException in project pravega by pravega.
the class ContainerKeyIndex method validateConditionalUpdate.
/**
* Validates a list of UpdateBatchItems against their actual Table Bucket offsets.
*
* @param items A list of {@link TableKeyBatch.Item} instances to validate.
* @param bucketOffsets A Map of Key Hashes to their corresponding offsets (versions). Each {@link TableKeyBatch.Item}
* will be looked up in this Map (based on the Item's KeyHash) and validated appropriately.
* @param segmentName The name of the segment on which the update is performed.
* @throws KeyNotExistsException If an UpdateBatchItem's Key does not exist in the Table but the item's version does
* not indicate that the key must not exist.
* @throws BadKeyVersionException If an UpdateBatchItem's Key does exist in the Table but the item's version is
* different from that key's version.
*/
@SneakyThrows(ConditionalTableUpdateException.class)
private void validateConditionalUpdate(List<TableKeyBatch.Item> items, Map<UUID, Long> bucketOffsets, String segmentName) {
// Key = Key that failed, Value = Key's bucket offset.
val badKeyVersions = new HashMap<TableKey, Long>();
for (val item : items) {
// Validate compareVersion.
TableKey key = item.getKey();
Long bucketOffset = bucketOffsets.get(item.getHash());
assert key.hasVersion() : "validateConditionalUpdate for TableKey with no compare version";
if (bucketOffset == TableKey.NOT_EXISTS) {
if (key.getVersion() != TableKey.NOT_EXISTS) {
// Key does not exist, but the conditional update provided a specific version.
throw new KeyNotExistsException(segmentName, key.getKey());
}
} else if (bucketOffset != key.getVersion()) {
// Key does exist, but has the wrong version.
badKeyVersions.put(key, bucketOffset);
}
}
if (!badKeyVersions.isEmpty()) {
// Throw the bad key version in bulk - helps speed verification.
throw new BadKeyVersionException(segmentName, badKeyVersions);
}
// All validations for all items passed.
}
Aggregations