use of org.apache.ratis.protocol.Message in project incubator-ratis by apache.
the class StateMachineUpdater method run.
@Override
public void run() {
final RaftStorage storage = server.getState().getStorage();
while (isRunning()) {
try {
synchronized (this) {
// Thus initially lastAppliedIndex can be greater than lastCommitted.
while (lastAppliedIndex >= raftLog.getLastCommittedIndex()) {
wait();
}
}
final long committedIndex = raftLog.getLastCommittedIndex();
Preconditions.assertTrue(lastAppliedIndex < committedIndex);
if (state == State.RELOAD) {
Preconditions.assertTrue(stateMachine.getLifeCycleState() == LifeCycle.State.PAUSED);
stateMachine.reinitialize(server.getId(), properties, storage);
SnapshotInfo snapshot = stateMachine.getLatestSnapshot();
Preconditions.assertTrue(snapshot != null && snapshot.getIndex() > lastAppliedIndex, "Snapshot: %s, lastAppliedIndex: %s", snapshot, lastAppliedIndex);
lastAppliedIndex = snapshot.getIndex();
lastSnapshotIndex = snapshot.getIndex();
state = State.RUNNING;
}
final MemoizedSupplier<List<CompletableFuture<Message>>> futures = MemoizedSupplier.valueOf(() -> new ArrayList<>());
while (lastAppliedIndex < committedIndex) {
final long nextIndex = lastAppliedIndex + 1;
final LogEntryProto next = raftLog.get(nextIndex);
if (next != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("{}: applying nextIndex={}, nextLog={}", this, nextIndex, ServerProtoUtils.toString(next));
}
final CompletableFuture<Message> f = server.applyLogToStateMachine(next);
if (f != null) {
futures.get().add(f);
}
lastAppliedIndex = nextIndex;
} else {
LOG.debug("{}: logEntry {} is null. There may be snapshot to load. state:{}", this, nextIndex, state);
break;
}
}
// check if need to trigger a snapshot
if (shouldTakeSnapshot(lastAppliedIndex)) {
if (futures.isInitialized()) {
JavaUtils.allOf(futures.get()).get();
}
stateMachine.takeSnapshot();
// TODO purge logs, including log cache. but should keep log for leader's RPCSenders
lastSnapshotIndex = lastAppliedIndex;
}
} catch (InterruptedException e) {
if (!isRunning()) {
LOG.info("{}: the StateMachineUpdater is interrupted and will exit.", this);
} else {
final String s = this + ": the StateMachineUpdater is wrongly interrupted";
ExitUtils.terminate(1, s, e, LOG);
}
} catch (Throwable t) {
final String s = this + ": the StateMachineUpdater hits Throwable";
ExitUtils.terminate(2, s, t, LOG);
}
}
}
use of org.apache.ratis.protocol.Message in project alluxio by Alluxio.
the class RaftJournalWriter method flush.
@Override
public void flush() throws IOException, JournalClosedException {
if (mClosed) {
throw new JournalClosedException("Cannot flush. Journal writer has been closed");
}
if (mJournalEntryBuilder != null) {
long flushSN = mNextSequenceNumberToWrite.get() - 1;
try {
// It is ok to submit the same entries multiple times because we de-duplicate by sequence
// number when applying them. This could happen if submit fails and we re-submit the same
// entry on retry.
JournalEntry entry = mJournalEntryBuilder.build();
Message message = RaftJournalSystem.toRaftMessage(entry);
mLastSubmittedSequenceNumber.set(flushSN);
LOG.trace("Flushing entry {} ({})", entry, message);
RaftClientReply reply = mClient.sendAsync(message, TimeDuration.valueOf(mWriteTimeoutMs, TimeUnit.MILLISECONDS)).get(mWriteTimeoutMs, TimeUnit.MILLISECONDS);
mLastCommittedSequenceNumber.set(flushSN);
if (reply.getException() != null) {
throw reply.getException();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException(e);
} catch (ExecutionException e) {
throw new IOException(e.getCause());
} catch (TimeoutException e) {
throw new IOException(String.format("Timed out after waiting %s milliseconds for journal entries to be processed", mWriteTimeoutMs), e);
}
mJournalEntryBuilder = null;
}
}
use of org.apache.ratis.protocol.Message in project alluxio by Alluxio.
the class JournalStateMachine method query.
@Override
public CompletableFuture<Message> query(Message request) {
CompletableFuture<Message> future = new CompletableFuture<>();
try {
JournalQueryRequest queryRequest = JournalQueryRequest.parseFrom(request.getContent().asReadOnlyByteBuffer());
LOG.debug("Received query request: {}", queryRequest);
// give snapshot manager a chance to handle snapshot related requests
Message reply = mSnapshotManager.handleRequest(queryRequest);
if (reply != null) {
future.complete(reply);
return future;
}
// other type of requests.
if (queryRequest.hasAddQuorumServerRequest()) {
AddQuorumServerRequest addRequest = queryRequest.getAddQuorumServerRequest();
return CompletableFuture.supplyAsync(() -> {
try {
mJournalSystem.addQuorumServer(addRequest.getServerAddress());
} catch (IOException e) {
throw new CompletionException(e);
}
return Message.EMPTY;
});
}
} catch (Exception e) {
LOG.error("failed processing request {}", request, e);
future.completeExceptionally(e);
return future;
}
return super.query(request);
}
use of org.apache.ratis.protocol.Message in project alluxio by Alluxio.
the class SnapshotReplicationManagerTest method before.
private void before(int numFollowers) throws Exception {
mLeader = Mockito.mock(RaftJournalSystem.class);
Mockito.when(mLeader.isLeader()).thenReturn(true);
Mockito.when(mLeader.getLocalPeerId()).thenReturn(RaftPeerId.getRaftPeerId("leader"));
mLeaderStore = getSimpleStateMachineStorage();
mLeaderSnapshotManager = Mockito.spy(new SnapshotReplicationManager(mLeader, mLeaderStore));
String serverName = InProcessServerBuilder.generateName();
mServer = InProcessServerBuilder.forName(serverName).directExecutor().addService(new RaftJournalServiceHandler(mLeaderSnapshotManager)).build();
mServer.start();
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
RaftJournalServiceGrpc.RaftJournalServiceStub stub = RaftJournalServiceGrpc.newStub(channel);
// mock RaftJournalServiceClient
mClient = Mockito.mock(RaftJournalServiceClient.class);
Mockito.doNothing().when(mClient).close();
// download rpc mock
Mockito.when(mClient.downloadSnapshot(any())).thenAnswer((args) -> {
StreamObserver responseObserver = args.getArgument(0, StreamObserver.class);
return stub.downloadSnapshot(responseObserver);
});
// upload rpc mock
Mockito.when(mClient.uploadSnapshot(any())).thenAnswer((args) -> {
StreamObserver responseObserver = args.getArgument(0, StreamObserver.class);
return stub.uploadSnapshot(responseObserver);
});
Mockito.doReturn(mClient).when(mLeaderSnapshotManager).getJournalServiceClient();
for (int i = 0; i < numFollowers; i++) {
Follower follower = new Follower(mClient);
mFollowers.put(follower.getRaftPeerId(), follower);
}
List<QuorumServerInfo> quorumServerInfos = mFollowers.values().stream().map(follower -> {
return QuorumServerInfo.newBuilder().setServerAddress(NetAddress.newBuilder().setHost(follower.mHost).setRpcPort(follower.mRpcPort)).build();
}).collect(Collectors.toList());
Mockito.when(mLeader.getQuorumServerInfoList()).thenReturn(quorumServerInfos);
Mockito.when(mLeader.sendMessageAsync(any(), any())).thenAnswer((args) -> {
RaftPeerId peerId = args.getArgument(0, RaftPeerId.class);
Message message = args.getArgument(1, Message.class);
JournalQueryRequest queryRequest = JournalQueryRequest.parseFrom(message.getContent().asReadOnlyByteBuffer());
Message response = mFollowers.get(peerId).mSnapshotManager.handleRequest(queryRequest);
RaftClientReply reply = Mockito.mock(RaftClientReply.class);
Mockito.when(reply.getMessage()).thenReturn(response);
return CompletableFuture.completedFuture(reply);
});
}
Aggregations