use of io.atomix.primitive.proxy.PrimitiveProxy in project atomix by atomix.
the class RaftFuzzTest method runFuzzTest.
/**
* Runs a single fuzz test.
*/
private void runFuzzTest() throws Exception {
reset();
createServers(randomNumber(5) + 3);
final Object lock = new Object();
final AtomicLong index = new AtomicLong();
final Map<Integer, Long> indexes = new HashMap<>();
ThreadContext context = new SingleThreadContext("fuzz-test");
int clients = randomNumber(10) + 1;
for (int i = 0; i < clients; i++) {
ReadConsistency consistency = randomConsistency();
RaftClient client = createClient();
PrimitiveProxy proxy = createProxy(client, consistency);
Scheduler scheduler = new SingleThreadContext("fuzz-test-" + i);
final int clientId = i;
scheduler.schedule(Duration.ofMillis((100 * clients) + (randomNumber(50) - 25)), Duration.ofMillis((100 * clients) + (randomNumber(50) - 25)), () -> {
long lastLinearizableIndex = index.get();
int type = randomNumber(4);
switch(type) {
case 0:
proxy.<Map.Entry<String, String>, Long>invoke(PUT, clientSerializer::encode, Maps.immutableEntry(randomKey(), randomString(1024 * 16)), clientSerializer::decode).thenAccept(result -> {
synchronized (lock) {
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
});
break;
case 1:
proxy.invoke(GET, clientSerializer::encode, randomKey(), clientSerializer::decode);
break;
case 2:
proxy.<String, Long>invoke(REMOVE, clientSerializer::encode, randomKey(), clientSerializer::decode).thenAccept(result -> {
synchronized (lock) {
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
});
break;
case 3:
proxy.<Long>invoke(INDEX, clientSerializer::decode).thenAccept(result -> {
synchronized (lock) {
switch(consistency) {
case LINEARIZABLE:
case LINEARIZABLE_LEASE:
if (result < lastLinearizableIndex) {
System.out.println(result + " is less than last linearizable index " + lastLinearizableIndex);
System.exit(1);
} else if (result > index.get()) {
index.set(result);
}
case SEQUENTIAL:
Long lastSequentialIndex = indexes.get(clientId);
if (lastSequentialIndex == null) {
indexes.put(clientId, result);
} else if (result < lastSequentialIndex) {
System.out.println(result + " is less than last sequential index " + lastSequentialIndex);
System.exit(1);
} else {
indexes.put(clientId, lastSequentialIndex);
}
}
}
});
}
});
}
scheduleRestarts(context);
Thread.sleep(Duration.ofMinutes(15).toMillis());
}
use of io.atomix.primitive.proxy.PrimitiveProxy in project atomix by atomix.
the class PrimaryBackupTest method testSequentialEvent.
/**
* Tests submitting a sequential event.
*/
private void testSequentialEvent(int nodes, int backups, Replication replication) throws Throwable {
createServers(nodes);
AtomicLong count = new AtomicLong();
AtomicLong index = new AtomicLong();
PrimaryBackupClient client = createClient();
PrimitiveProxy session = createProxy(client, backups, replication);
session.<Long>addEventListener(CHANGE_EVENT, SERIALIZER::decode, event -> {
threadAssertEquals(count.incrementAndGet(), 2L);
threadAssertEquals(index.get(), event);
resume();
});
session.<Boolean, Long>invoke(EVENT, SERIALIZER::encode, true, SERIALIZER::decode).thenAccept(result -> {
threadAssertNotNull(result);
threadAssertEquals(count.incrementAndGet(), 1L);
index.set(result);
resume();
});
await(5000, 2);
}
use of io.atomix.primitive.proxy.PrimitiveProxy in project atomix by atomix.
the class PrimaryBackupTest method testEvents.
/**
* Tests submitting sequential events to all sessions.
*/
private void testEvents(int nodes, int backups, Replication replication) throws Throwable {
createServers(nodes);
PrimaryBackupClient client1 = createClient();
PrimitiveProxy session1 = createProxy(client1, backups, replication);
session1.addEventListener(event -> {
threadAssertNotNull(event);
resume();
});
PrimaryBackupClient client2 = createClient();
PrimitiveProxy session2 = createProxy(client2, backups, replication);
session2.addEventListener(event -> {
threadAssertNotNull(event);
resume();
});
session1.invoke(READ).thenRun(this::resume);
session2.invoke(READ).thenRun(this::resume);
await(5000, 2);
session1.invoke(EVENT, SERIALIZER::encode, false).thenRun(this::resume);
await(5000, 3);
}
use of io.atomix.primitive.proxy.PrimitiveProxy in project atomix by atomix.
the class PrimaryBackupTest method testManyEventsAfterPrimaryShutdown.
/**
* Tests events after a primary shutdown.
*/
private void testManyEventsAfterPrimaryShutdown(Replication replication) throws Throwable {
List<PrimaryBackupServer> servers = createServers(5);
PrimaryBackupClient client = createClient();
PrimitiveProxy session = createProxy(client, 3, replication);
session.addEventListener(event -> {
threadAssertNotNull(event);
resume();
});
for (int i = 0; i < 10; i++) {
session.invoke(EVENT, SERIALIZER::encode, true).thenRun(this::resume);
await(5000, 2);
}
PrimaryBackupServer leader = servers.stream().filter(s -> s.getRole() == Role.PRIMARY).findFirst().get();
leader.stop().get(10, TimeUnit.SECONDS);
for (int i = 0; i < 10; i++) {
session.invoke(EVENT, SERIALIZER::encode, true).thenRun(this::resume);
await(5000, 2);
}
}
use of io.atomix.primitive.proxy.PrimitiveProxy in project atomix by atomix.
the class DefaultRaftClient method newProxy.
@Override
public PrimitiveProxy newProxy(String primitiveName, PrimitiveType primitiveType, RaftProtocol primitiveProtocol) {
// Create a proxy builder that uses the session manager to open a session.
Supplier<PrimitiveProxy> proxyFactory = () -> new DefaultRaftProxy(primitiveName, primitiveType, DefaultRaftClient.this.protocol, selectorManager, sessionManager, primitiveProtocol.readConsistency(), primitiveProtocol.communicationStrategy(), threadContextFactory.createContext(), primitiveProtocol.minTimeout(), primitiveProtocol.maxTimeout());
PrimitiveProxy proxy;
// If the recovery strategy is set to RECOVER, wrap the builder in a recovering proxy client.
if (primitiveProtocol.recoveryStrategy() == Recovery.RECOVER) {
proxy = new RecoveringPrimitiveProxy(clientId, primitiveName, primitiveType, proxyFactory, threadContextFactory.createContext());
} else {
proxy = proxyFactory.get();
}
// If max retries is set, wrap the client in a retrying proxy client.
if (primitiveProtocol.maxRetries() > 0) {
proxy = new RetryingPrimitiveProxy(proxy, threadContextFactory.createContext(), primitiveProtocol.maxRetries(), primitiveProtocol.retryDelay());
}
// Default the executor to use the configured thread pool executor and create a blocking aware proxy client.
Executor executor = primitiveProtocol.executor() != null ? primitiveProtocol.executor() : threadContextFactory.createContext();
return new BlockingAwarePrimitiveProxy(proxy, executor);
}
Aggregations