use of org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo in project alluxio by Alluxio.
the class SnapshotDownloader method onNextInternal.
private void onNextInternal(R response) throws IOException {
TermIndex termIndex = TermIndex.valueOf(mDataGetter.apply(response).getSnapshotTerm(), mDataGetter.apply(response).getSnapshotIndex());
if (mTermIndex == null) {
LOG.info("Downloading new snapshot {} from {}", termIndex, mSource);
mTermIndex = termIndex;
// start a new file
mTempFile = RaftJournalUtils.createTempSnapshotFile(mStorage);
mTempFile.deleteOnExit();
mStream.onNext(mMessageBuilder.apply(0L));
} else {
if (!termIndex.equals(mTermIndex)) {
throw new IOException(String.format("Mismatched term index when downloading the snapshot. expected: %s actual: %s", mTermIndex, termIndex));
}
if (!mDataGetter.apply(response).hasChunk()) {
throw new IOException(String.format("A chunk for file %s is missing from the response %s.", mTempFile, response));
}
// write the chunk
if (mOutputStream == null) {
LOG.info("Start writing to temporary file {}", mTempFile.getPath());
mOutputStream = new FileOutputStream(mTempFile);
}
long position = mOutputStream.getChannel().position();
if (position != mDataGetter.apply(response).getOffset()) {
throw new IOException(String.format("Mismatched offset in file %d, expect %d, bytes written %d", position, mDataGetter.apply(response).getOffset(), mBytesWritten));
}
mOutputStream.write(mDataGetter.apply(response).getChunk().toByteArray());
mBytesWritten += mDataGetter.apply(response).getChunk().size();
LOG.debug("Written {} bytes to snapshot file {}", mBytesWritten, mTempFile.getPath());
if (mDataGetter.apply(response).getEof()) {
LOG.debug("Completed writing to temporary file {} with size {}", mTempFile.getPath(), mOutputStream.getChannel().position());
mOutputStream.close();
mOutputStream = null;
final MD5Hash digest = MD5FileUtil.computeMd5ForFile(mTempFile);
mSnapshotToInstall = new SingleFileSnapshotInfo(new FileInfo(mTempFile.toPath(), digest), mTermIndex.getTerm(), mTermIndex.getIndex());
mFuture.complete(mTermIndex);
LOG.info("Finished copying snapshot to local file {}.", mTempFile);
mStream.onCompleted();
} else {
mStream.onNext(mMessageBuilder.apply(mBytesWritten));
}
}
}
use of org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo in project alluxio by Alluxio.
the class SnapshotReplicationManager method requestInfo.
private void requestInfo() {
Preconditions.checkState(mDownloadState.get() == DownloadState.REQUEST_INFO);
try {
SingleFileSnapshotInfo latestSnapshot = mStorage.getLatestSnapshot();
SnapshotMetadata snapshotMetadata = latestSnapshot == null ? null : SnapshotMetadata.newBuilder().setSnapshotTerm(latestSnapshot.getTerm()).setSnapshotIndex(latestSnapshot.getIndex()).build();
// build SnapshotInfoRequests
Map<RaftPeerId, CompletableFuture<RaftClientReply>> jobs = mJournalSystem.getQuorumServerInfoList().stream().filter(server -> server.getServerState() == QuorumServerState.AVAILABLE).map(server -> RaftJournalUtils.getPeerId(server.getServerAddress().getHost(), server.getServerAddress().getRpcPort())).filter(peerId -> !peerId.equals(mJournalSystem.getLocalPeerId())).collect(Collectors.toMap(Function.identity(), peerId -> mJournalSystem.sendMessageAsync(peerId, toMessage(JournalQueryRequest.newBuilder().setSnapshotInfoRequest(GetSnapshotInfoRequest.getDefaultInstance()).build()))));
// query all secondary masters for information about their latest snapshot
for (Map.Entry<RaftPeerId, CompletableFuture<RaftClientReply>> job : jobs.entrySet()) {
RaftPeerId peerId = job.getKey();
try {
RaftClientReply reply = job.getValue().get();
if (reply.getException() != null) {
throw reply.getException();
}
JournalQueryResponse response = JournalQueryResponse.parseFrom(reply.getMessage().getContent().asReadOnlyByteBuffer());
if (!response.hasSnapshotInfoResponse()) {
throw new IOException("Invalid response for GetSnapshotInfoRequest " + response);
}
LOG.debug("Received snapshot info from follower {} - {}", peerId, response);
SnapshotMetadata latest = response.getSnapshotInfoResponse().getLatest();
if (snapshotMetadata == null || (latest.getSnapshotTerm() >= snapshotMetadata.getSnapshotTerm()) && latest.getSnapshotIndex() > snapshotMetadata.getSnapshotIndex()) {
mSnapshotCandidates.add(new Pair<>(latest, peerId));
}
} catch (Exception e) {
LOG.warn("Error while requesting snapshot info from {}: {}", peerId, e.toString());
}
}
} catch (Exception e) {
LogUtils.warnWithException(LOG, "Failed to request snapshot info from followers", e);
}
}
use of org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo in project alluxio by Alluxio.
the class SnapshotReplicationManagerTest method validateSnapshotFile.
private void validateSnapshotFile(SimpleStateMachineStorage storage, long term, long index) throws IOException {
SingleFileSnapshotInfo snapshot = storage.getLatestSnapshot();
Assert.assertNotNull(snapshot);
Assert.assertEquals(TermIndex.valueOf(term, index), snapshot.getTermIndex());
byte[] received = FileUtils.readFileToByteArray(snapshot.getFiles().get(0).getPath().toFile());
Assert.assertTrue(BufferUtils.equalIncreasingByteArray(SNAPSHOT_SIZE, received));
}
use of org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo in project alluxio by Alluxio.
the class SnapshotReplicationManagerTest method downloadFailure.
/**
* Simulates a {@link SnapshotDownloader} error.
*/
@Test
public void downloadFailure() throws Exception {
before(2);
List<Follower> followers = new ArrayList<>(mFollowers.values());
Follower firstFollower = followers.get(0);
Follower secondFollower = followers.get(1);
// create default 0, 1 snapshot
createSnapshotFile(firstFollower.mStore);
// preferable to the default 0, 1 snapshot
createSnapshotFile(secondFollower.mStore, 0, 2);
// make sure to error out when requesting the better snapshot from secondFollower
Mockito.doAnswer(mock -> {
SingleFileSnapshotInfo snapshot = secondFollower.mStore.getLatestSnapshot();
StreamObserver<UploadSnapshotPResponse> responseObserver = SnapshotUploader.forFollower(secondFollower.mStore, snapshot);
StreamObserver<UploadSnapshotPRequest> requestObserver = mClient.uploadSnapshot(responseObserver);
requestObserver.onError(new IOException("failed snapshot upload"));
return null;
}).when(secondFollower.mSnapshotManager).sendSnapshotToLeader();
mLeaderSnapshotManager.maybeCopySnapshotFromFollower();
CommonUtils.waitFor("leader snapshot to complete", () -> mLeaderSnapshotManager.maybeCopySnapshotFromFollower() != -1, mWaitOptions);
// verify that the leader still requests and gets second best snapshot
validateSnapshotFile(mLeaderStore);
}
use of org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo in project alluxio by Alluxio.
the class SnapshotReplicationManagerTest method uploadFailure.
/**
* Simulates a {@link SnapshotUploader} error.
*/
@Test
public void uploadFailure() throws Exception {
before(2);
List<Follower> followers = new ArrayList<>(mFollowers.values());
Follower firstFollower = followers.get(0);
Follower secondFollower = followers.get(1);
// create default 0, 1 snapshot
createSnapshotFile(firstFollower.mStore);
// preferable to the default 0, 1 snapshot
createSnapshotFile(secondFollower.mStore, 0, 2);
// make sure to error out when requesting the better snapshot from secondFollower
Mockito.doAnswer(mock -> {
SingleFileSnapshotInfo snapshot = secondFollower.mStore.getLatestSnapshot();
StreamObserver<UploadSnapshotPResponse> responseObserver = SnapshotUploader.forFollower(secondFollower.mStore, snapshot);
StreamObserver<UploadSnapshotPRequest> requestObserver = mClient.uploadSnapshot(responseObserver);
responseObserver.onError(new StatusRuntimeException(Status.UNAVAILABLE));
requestObserver.onNext(UploadSnapshotPRequest.newBuilder().setData(SnapshotData.newBuilder().setSnapshotTerm(snapshot.getTerm()).setSnapshotIndex(snapshot.getIndex()).setOffset(0)).build());
return null;
}).when(secondFollower.mSnapshotManager).sendSnapshotToLeader();
mLeaderSnapshotManager.maybeCopySnapshotFromFollower();
CommonUtils.waitFor("leader snapshot to complete", () -> mLeaderSnapshotManager.maybeCopySnapshotFromFollower() != -1, mWaitOptions);
// verify that the leader still requests and gets second best snapshot
validateSnapshotFile(mLeaderStore);
}
Aggregations