use of io.pravega.controller.server.WireCommandFailedException in project pravega by pravega.
the class PravegaTablesStoreHelper method exceptionalCallback.
private <T> Supplier<CompletableFuture<T>> exceptionalCallback(Supplier<CompletableFuture<T>> future, Supplier<String> errorMessageSupplier, boolean throwOriginalOnCFE, long requestId) {
return () -> CompletableFuture.completedFuture(null).thenComposeAsync(v -> future.get(), executor).exceptionally(t -> {
String errorMessage = errorMessageSupplier.get();
Throwable cause = Exceptions.unwrap(t);
Throwable toThrow;
if (cause instanceof WireCommandFailedException) {
WireCommandFailedException wcfe = (WireCommandFailedException) cause;
switch(wcfe.getReason()) {
case ConnectionDropped:
case ConnectionFailed:
toThrow = throwOriginalOnCFE ? wcfe : StoreException.create(StoreException.Type.CONNECTION_ERROR, wcfe, errorMessage);
break;
case UnknownHost:
toThrow = StoreException.create(StoreException.Type.CONNECTION_ERROR, wcfe, errorMessage);
break;
case PreconditionFailed:
toThrow = StoreException.create(StoreException.Type.ILLEGAL_STATE, wcfe, errorMessage);
break;
case AuthFailed:
authToken.set(authHelper.retrieveMasterToken());
toThrow = StoreException.create(StoreException.Type.CONNECTION_ERROR, wcfe, errorMessage);
break;
case SegmentDoesNotExist:
toThrow = StoreException.create(StoreException.Type.DATA_CONTAINER_NOT_FOUND, wcfe, errorMessage);
break;
case TableSegmentNotEmpty:
toThrow = StoreException.create(StoreException.Type.DATA_CONTAINS_ELEMENTS, wcfe, errorMessage);
break;
case TableKeyDoesNotExist:
toThrow = StoreException.create(StoreException.Type.DATA_NOT_FOUND, wcfe, errorMessage);
break;
case TableKeyBadVersion:
toThrow = StoreException.create(StoreException.Type.WRITE_CONFLICT, wcfe, errorMessage);
break;
default:
toThrow = StoreException.create(StoreException.Type.UNKNOWN, wcfe, errorMessage);
}
} else if (cause instanceof HostStoreException) {
log.warn(requestId, "Host Store exception {}", cause.getMessage());
toThrow = StoreException.create(StoreException.Type.CONNECTION_ERROR, cause, errorMessage);
} else {
log.warn(requestId, "exception of unknown type thrown {} ", errorMessage, cause);
toThrow = StoreException.create(StoreException.Type.UNKNOWN, cause, errorMessage);
}
throw new CompletionException(toThrow);
});
}
use of io.pravega.controller.server.WireCommandFailedException in project pravega by pravega.
the class PravegaTablesStoreHelperTest method testRetriesExhausted.
@Test
public void testRetriesExhausted() {
SegmentHelper segmentHelper = spy(SegmentHelperMock.getSegmentHelperMockForTables(executor));
GrpcAuthHelper authHelper = GrpcAuthHelper.getDisabledAuthHelper();
PravegaTablesStoreHelper storeHelper = new PravegaTablesStoreHelper(segmentHelper, authHelper, executor, 2);
CompletableFuture<Void> connectionDropped = Futures.failedFuture(new WireCommandFailedException(WireCommandType.CREATE_TABLE_SEGMENT, WireCommandFailedException.Reason.ConnectionDropped));
doAnswer(x -> connectionDropped).when(segmentHelper).createTableSegment(anyString(), anyString(), anyLong(), anyBoolean(), anyInt(), anyLong());
AssertExtensions.assertFutureThrows("ConnectionDropped", storeHelper.createTable("table", 0L), e -> Exceptions.unwrap(e) instanceof StoreException.StoreConnectionException);
CompletableFuture<Void> connectionFailed = Futures.failedFuture(new WireCommandFailedException(WireCommandType.CREATE_TABLE_SEGMENT, WireCommandFailedException.Reason.ConnectionFailed));
doAnswer(x -> connectionFailed).when(segmentHelper).createTableSegment(anyString(), anyString(), anyLong(), anyBoolean(), anyInt(), anyLong());
AssertExtensions.assertFutureThrows("ConnectionFailed", storeHelper.createTable("table", 0L), e -> Exceptions.unwrap(e) instanceof StoreException.StoreConnectionException);
CompletableFuture<Void> authFailed = Futures.failedFuture(new WireCommandFailedException(WireCommandType.CREATE_TABLE_SEGMENT, WireCommandFailedException.Reason.AuthFailed));
doAnswer(x -> connectionFailed).when(segmentHelper).createTableSegment(anyString(), anyString(), anyLong(), anyBoolean(), anyInt(), anyLong());
AssertExtensions.assertFutureThrows("AuthFailed", storeHelper.createTable("table", 0L), e -> Exceptions.unwrap(e) instanceof StoreException.StoreConnectionException);
}
use of io.pravega.controller.server.WireCommandFailedException in project pravega by pravega.
the class SegmentHelperMock method getSegmentHelperMockForTables.
public static SegmentHelper getSegmentHelperMockForTables(ScheduledExecutorService executor) {
SegmentHelper helper = getSegmentHelperMock();
final Object lock = new Object();
final Map<String, Map<ByteBuffer, TableSegmentEntry>> mapOfTables = new HashMap<>();
final Map<String, Map<ByteBuffer, Long>> mapOfTablesPosition = new HashMap<>();
// region create table
doAnswer(x -> {
String tableName = x.getArgument(0);
return CompletableFuture.runAsync(() -> {
synchronized (lock) {
mapOfTables.putIfAbsent(tableName, new HashMap<>());
mapOfTablesPosition.putIfAbsent(tableName, new HashMap<>());
}
}, executor);
}).when(helper).createTableSegment(anyString(), anyString(), anyLong(), anyBoolean(), anyInt(), anyLong());
// endregion
// region delete table
doAnswer(x -> {
String tableName = x.getArgument(0);
Boolean mustBeEmpty = x.getArgument(1);
final WireCommandType type = WireCommandType.DELETE_TABLE_SEGMENT;
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
if (!mapOfTables.containsKey(tableName)) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
}
boolean empty = Optional.ofNullable(mapOfTables.get(tableName)).orElse(Collections.emptyMap()).isEmpty();
if (!mustBeEmpty || empty) {
mapOfTables.remove(tableName);
mapOfTablesPosition.remove(tableName);
return null;
} else {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.TableSegmentNotEmpty);
}
}
}, executor);
}).when(helper).deleteTableSegment(anyString(), anyBoolean(), anyString(), anyLong());
// endregion
// region update keys
doAnswer(x -> {
final WireCommandType type = WireCommandType.UPDATE_TABLE_ENTRIES;
String tableName = x.getArgument(0);
List<TableSegmentEntry> entries = x.getArgument(1);
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
Map<ByteBuffer, TableSegmentEntry> table = mapOfTables.get(tableName);
Map<ByteBuffer, Long> tablePos = mapOfTablesPosition.get(tableName);
if (table == null) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
} else {
List<TableSegmentKeyVersion> resultList = new LinkedList<>();
entries.forEach(entry -> {
ByteBuffer key = entry.getKey().getKey().copy().nioBuffer();
byte[] value = entry.getValue().copy().array();
TableSegmentEntry existingEntry = table.get(key);
if (existingEntry == null) {
if (entry.getKey().getVersion().equals(TableSegmentKeyVersion.NOT_EXISTS)) {
TableSegmentEntry newEntry = TableSegmentEntry.versioned(key.array(), value, 0);
table.put(key, newEntry);
tablePos.put(key, System.nanoTime());
resultList.add(newEntry.getKey().getVersion());
} else {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.TableKeyDoesNotExist);
}
} else if (existingEntry.getKey().getVersion().equals(entry.getKey().getVersion())) {
TableSegmentKeyVersion newVersion = TableSegmentKeyVersion.from(existingEntry.getKey().getVersion().getSegmentVersion() + 1);
TableSegmentEntry newEntry = TableSegmentEntry.versioned(key.array(), value, newVersion.getSegmentVersion());
table.put(key, newEntry);
tablePos.put(key, System.nanoTime());
resultList.add(newVersion);
} else {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.TableKeyBadVersion);
}
});
return resultList;
}
}
}, executor);
}).when(helper).updateTableEntries(anyString(), any(), anyString(), anyLong());
// endregion
// region remove keys
doAnswer(x -> {
final WireCommandType type = WireCommandType.REMOVE_TABLE_KEYS;
String tableName = x.getArgument(0);
List<TableSegmentKey> keys = x.getArgument(1);
return CompletableFuture.runAsync(() -> {
synchronized (lock) {
Map<ByteBuffer, TableSegmentEntry> table = mapOfTables.get(tableName);
Map<ByteBuffer, Long> tablePos = mapOfTablesPosition.get(tableName);
if (table == null) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
} else {
keys.forEach(rawKey -> {
ByteBuffer key = rawKey.getKey().copy().nioBuffer();
TableSegmentEntry existingEntry = table.get(key);
if (existingEntry != null) {
if (existingEntry.getKey().getVersion().equals(rawKey.getVersion()) || rawKey.getVersion() == null || rawKey.getVersion().equals(TableSegmentKeyVersion.NO_VERSION)) {
table.remove(key);
tablePos.remove(key);
} else {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.TableKeyBadVersion);
}
}
});
}
}
}, executor);
}).when(helper).removeTableKeys(anyString(), any(), anyString(), anyLong());
// endregion
// region read keys
doAnswer(x -> {
final WireCommandType type = WireCommandType.READ_TABLE;
String tableName = x.getArgument(0);
List<TableSegmentKey> requestKeys = x.getArgument(1);
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
Map<ByteBuffer, TableSegmentEntry> table = mapOfTables.get(tableName);
if (table == null) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
} else {
List<TableSegmentEntry> resultList = new LinkedList<>();
requestKeys.forEach(requestKey -> {
ByteBuffer key = requestKey.getKey().copy().nioBuffer();
TableSegmentEntry existingEntry = table.get(key);
if (existingEntry == null) {
resultList.add(TableSegmentEntry.notExists(key.array(), new byte[0]));
} else if (existingEntry.getKey().getVersion().equals(requestKey.getVersion()) || requestKey.getVersion() == null || requestKey.getVersion().equals(TableSegmentKeyVersion.NO_VERSION)) {
resultList.add(duplicate(existingEntry));
} else {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.TableKeyBadVersion);
}
});
return resultList;
}
}
}, executor);
}).when(helper).readTable(anyString(), any(), anyString(), anyLong());
// endregion
// region readTableKeys
doAnswer(x -> {
String tableName = x.getArgument(0);
int limit = x.getArgument(1);
HashTableIteratorItem.State state = x.getArgument(2);
final WireCommandType type = WireCommandType.READ_TABLE;
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
Map<ByteBuffer, TableSegmentEntry> table = mapOfTables.get(tableName);
Map<ByteBuffer, Long> tablePos = mapOfTablesPosition.get(tableName);
if (table == null) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
} else {
long floor;
if (state.equals(HashTableIteratorItem.State.EMPTY)) {
floor = 0L;
} else {
floor = new ByteArraySegment(state.toBytes()).getLong(0);
}
AtomicLong token = new AtomicLong(floor);
List<TableSegmentKey> list = tablePos.entrySet().stream().sorted(Comparator.comparingLong(Map.Entry::getValue)).filter(c -> c.getValue() > floor).map(r -> {
token.set(r.getValue());
return duplicate(table.get(r.getKey()).getKey());
}).limit(limit).collect(Collectors.toList());
byte[] continuationToken = new byte[Long.BYTES];
BitConverter.writeLong(continuationToken, 0, token.get());
HashTableIteratorItem.State newState = HashTableIteratorItem.State.fromBytes(Unpooled.wrappedBuffer(continuationToken));
return new HashTableIteratorItem<>(newState, list);
}
}
}, executor);
}).when(helper).readTableKeys(anyString(), anyInt(), any(), anyString(), anyLong());
// endregion
// region readTableEntries
doAnswer(x -> {
String tableName = x.getArgument(0);
int limit = x.getArgument(1);
HashTableIteratorItem.State state = x.getArgument(2);
final WireCommandType type = WireCommandType.READ_TABLE;
return CompletableFuture.supplyAsync(() -> {
synchronized (lock) {
Map<ByteBuffer, TableSegmentEntry> table = mapOfTables.get(tableName);
Map<ByteBuffer, Long> tablePos = mapOfTablesPosition.get(tableName);
if (table == null) {
throw new WireCommandFailedException(type, WireCommandFailedException.Reason.SegmentDoesNotExist);
} else {
long floor;
if (state.equals(HashTableIteratorItem.State.EMPTY)) {
floor = 0L;
} else {
floor = new ByteArraySegment(state.toBytes()).getLong(0);
}
AtomicLong token = new AtomicLong(floor);
List<TableSegmentEntry> list = tablePos.entrySet().stream().sorted(Comparator.comparingLong(Map.Entry::getValue)).filter(c -> c.getValue() > floor).map(r -> {
token.set(r.getValue());
return duplicate(table.get(r.getKey()));
}).limit(limit).collect(Collectors.toList());
byte[] continuationToken = new byte[Long.BYTES];
BitConverter.writeLong(continuationToken, 0, token.get());
HashTableIteratorItem.State newState = HashTableIteratorItem.State.fromBytes(Unpooled.wrappedBuffer(continuationToken));
return new HashTableIteratorItem<>(newState, list);
}
}
}, executor);
}).when(helper).readTableEntries(anyString(), anyInt(), any(), anyString(), anyLong());
// endregion
return helper;
}
use of io.pravega.controller.server.WireCommandFailedException in project pravega by pravega.
the class RequestHandlersTest method testCommitFailureOnNoSuchSegment.
@Test(timeout = 10000)
public void testCommitFailureOnNoSuchSegment() {
CommitRequestHandler requestHandler = new CommitRequestHandler(streamStore, streamMetadataTasks, streamTransactionMetadataTasks, bucketStore, executor);
String noSuchSegment = "noSuchSegment";
streamStore.createScope(noSuchSegment, null, executor).join();
streamMetadataTasks.createStream(noSuchSegment, noSuchSegment, StreamConfiguration.builder().scalingPolicy(ScalingPolicy.fixed(1)).build(), System.currentTimeMillis(), 0L).join();
UUID txn = streamTransactionMetadataTasks.createTxn(noSuchSegment, noSuchSegment, 30000, 0L, 1024 * 1024L).join().getKey().getId();
streamStore.sealTransaction(noSuchSegment, noSuchSegment, txn, true, Optional.empty(), "", Long.MIN_VALUE, null, executor).join();
// 1. set segment helper mock to throw exception
doAnswer(x -> Futures.failedFuture(new WireCommandFailedException(WireCommandType.NO_SUCH_SEGMENT, WireCommandFailedException.Reason.SegmentDoesNotExist))).when(segmentHelper).mergeTxnSegments(anyString(), anyString(), anyLong(), anyLong(), any(), anyString(), anyLong());
streamStore.startCommitTransactions(noSuchSegment, noSuchSegment, 100, null, executor).join();
streamStore.setState(noSuchSegment, noSuchSegment, State.COMMITTING_TXN, null, executor).join();
assertEquals(State.COMMITTING_TXN, streamStore.getState(noSuchSegment, noSuchSegment, true, null, executor).join());
CommitEvent event = new CommitEvent(noSuchSegment, noSuchSegment, 0);
AssertExtensions.assertFutureThrows("", requestHandler.process(event, () -> false), e -> Exceptions.unwrap(e) instanceof IllegalStateException);
verify(segmentHelper, atLeastOnce()).mergeTxnSegments(anyString(), anyString(), anyLong(), anyLong(), any(), anyString(), anyLong());
}
use of io.pravega.controller.server.WireCommandFailedException in project pravega by pravega.
the class PravegaTablesKVTMetadataStoreTest method testPartiallyDeletedScope.
@Test(timeout = 30000)
public void testPartiallyDeletedScope() throws Exception {
final String scopeName = "partialScope";
PravegaTablesStoreHelper storeHelperSpy = spy(new PravegaTablesStoreHelper(segmentHelperMockForTables, GrpcAuthHelper.getDisabledAuthHelper(), executor));
WireCommandFailedException wcfe = new WireCommandFailedException(WireCommandType.READ_TABLE_KEYS, WireCommandFailedException.Reason.TableKeyDoesNotExist);
when(storeHelperSpy.getKeysPaginated(anyString(), any(), anyInt(), anyLong())).thenReturn(CompletableFuture.failedFuture(new CompletionException(StoreException.create(StoreException.Type.DATA_NOT_FOUND, wcfe, "kvTablesInScope not found."))));
StreamMetadataStore testStreamStore = TestStreamStoreFactory.createPravegaTablesStreamStore(PRAVEGA_ZK_CURATOR_RESOURCE.client, executor, storeHelperSpy);
KVTableMetadataStore testKVStore = TestStreamStoreFactory.createPravegaTablesKVStore(PRAVEGA_ZK_CURATOR_RESOURCE.client, executor, storeHelperSpy);
OperationContext context = testStreamStore.createScopeContext(scopeName, 0L);
CompletableFuture<Controller.CreateScopeStatus> createScopeFuture = testStreamStore.createScope(scopeName, context, executor);
Controller.CreateScopeStatus status = createScopeFuture.get();
Assert.assertEquals(Controller.CreateScopeStatus.Status.SUCCESS, status.getStatus());
String token = Controller.ContinuationToken.newBuilder().build().getToken();
Pair<List<String>, String> kvtList = testKVStore.listKeyValueTables(scopeName, token, 2, context, executor).get();
Assert.assertEquals(0, kvtList.getKey().size());
Assert.assertEquals(token, kvtList.getValue());
}
Aggregations