Search in sources :

Example 1 with FileChunkProto

use of org.apache.ratis.shaded.proto.RaftProtos.FileChunkProto in project incubator-ratis by apache.

the class SnapshotManager method installSnapshot.

public void installSnapshot(StateMachine stateMachine, InstallSnapshotRequestProto request) throws IOException {
    final long lastIncludedIndex = request.getTermIndex().getIndex();
    final RaftStorageDirectory dir = storage.getStorageDir();
    File tmpDir = dir.getNewTempDir();
    FileUtils.createDirectories(tmpDir);
    tmpDir.deleteOnExit();
    LOG.info("Installing snapshot:{}, to tmp dir:{}", request, tmpDir);
    for (FileChunkProto chunk : request.getFileChunksList()) {
        SnapshotInfo pi = stateMachine.getLatestSnapshot();
        if (pi != null && pi.getTermIndex().getIndex() >= lastIncludedIndex) {
            throw new IOException("There exists snapshot file " + pi.getFiles() + " in " + selfId + " with endIndex >= lastIncludedIndex " + lastIncludedIndex);
        }
        // this is relative to the root dir
        String fileName = chunk.getFilename();
        // TODO: assumes flat layout inside SM dir
        File tmpSnapshotFile = new File(tmpDir, new File(dir.getRoot(), fileName).getName());
        FileOutputStream out = null;
        try {
            // same last index.
            if (chunk.getOffset() == 0) {
                if (tmpSnapshotFile.exists()) {
                    FileUtils.deleteFully(tmpSnapshotFile);
                }
                // create the temp snapshot file and put padding inside
                out = new FileOutputStream(tmpSnapshotFile);
            } else {
                Preconditions.assertTrue(tmpSnapshotFile.exists());
                out = new FileOutputStream(tmpSnapshotFile, true);
                FileChannel fc = out.getChannel();
                fc.position(chunk.getOffset());
            }
            // write data to the file
            out.write(chunk.getData().toByteArray());
        } finally {
            IOUtils.cleanup(null, out);
        }
        // the md5 digest and create the md5 meta-file.
        if (chunk.getDone()) {
            final MD5Hash expectedDigest = new MD5Hash(chunk.getFileDigest().toByteArray());
            // calculate the checksum of the snapshot file and compare it with the
            // file digest in the request
            MD5Hash digest = MD5FileUtil.computeMd5ForFile(tmpSnapshotFile);
            if (!digest.equals(expectedDigest)) {
                LOG.warn("The snapshot md5 digest {} does not match expected {}", digest, expectedDigest);
                // dir.getCorruptSnapshotFile(lastIncludedTerm, lastIncludedIndex));
                throw new IOException("MD5 mismatch for snapshot-" + lastIncludedIndex + " installation");
            } else {
                MD5FileUtil.saveMD5File(tmpSnapshotFile, digest);
            }
        }
    }
    if (request.getDone()) {
        LOG.info("Install snapshot is done, renaming tnp dir:{} to:{}", tmpDir, dir.getStateMachineDir());
        dir.getStateMachineDir().delete();
        tmpDir.renameTo(dir.getStateMachineDir());
    }
}
Also used : SnapshotInfo(org.apache.ratis.statemachine.SnapshotInfo) FileChannel(java.nio.channels.FileChannel) FileOutputStream(java.io.FileOutputStream) FileChunkProto(org.apache.ratis.shaded.proto.RaftProtos.FileChunkProto) MD5Hash(org.apache.ratis.io.MD5Hash) IOException(java.io.IOException) File(java.io.File)

Aggregations

File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 FileChannel (java.nio.channels.FileChannel)1 MD5Hash (org.apache.ratis.io.MD5Hash)1 FileChunkProto (org.apache.ratis.shaded.proto.RaftProtos.FileChunkProto)1 SnapshotInfo (org.apache.ratis.statemachine.SnapshotInfo)1