org.apache.reef.io.checkpoint.fs.FSCheckpointService.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.reef.io.checkpoint.fs.FSCheckpointService.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.reef.io.checkpoint.fs;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.reef.io.checkpoint.CheckpointID;
import org.apache.reef.io.checkpoint.CheckpointNamingService;
import org.apache.reef.io.checkpoint.CheckpointService;
import org.apache.reef.tang.annotations.Name;
import org.apache.reef.tang.annotations.NamedParameter;
import org.apache.reef.tang.annotations.Parameter;

import javax.inject.Inject;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

/**
 * A FileSystem based CheckpointService.
 */
public class FSCheckpointService implements CheckpointService {

    private final Path base;
    private final FileSystem fs;
    private final CheckpointNamingService namingPolicy;
    private final short replication;

    @Inject
    FSCheckpointService(final FileSystem fs, final @Parameter(PATH.class) String basePath,
            final CheckpointNamingService namingPolicy,
            final @Parameter(REPLICATION_FACTOR.class) short replication) {
        this.fs = fs;
        this.base = new Path(basePath);
        this.namingPolicy = namingPolicy;
        this.replication = replication;
    }

    public FSCheckpointService(final FileSystem fs, final Path base, final CheckpointNamingService namingPolicy,
            final short replication) {
        this.fs = fs;
        this.base = base;
        this.namingPolicy = namingPolicy;
        this.replication = replication;
    }

    static final Path tmpfile(final Path p) {
        return new Path(p.getParent(), p.getName() + ".tmp");
    }

    public CheckpointWriteChannel create() throws IOException {

        final String name = namingPolicy.getNewName();

        final Path p = new Path(name);
        if (p.isUriPathAbsolute()) {
            throw new IOException("Checkpoint cannot be an absolute path");
        }
        return createInternal(new Path(base, p));
    }

    CheckpointWriteChannel createInternal(Path name) throws IOException {

        //create a temp file, fail if file exists
        return new FSCheckpointWriteChannel(name, fs.create(tmpfile(name), replication));
    }

    @Override
    public CheckpointReadChannel open(final CheckpointID id) throws IOException, InterruptedException {
        if (!(id instanceof FSCheckpointID)) {
            throw new IllegalArgumentException("Mismatched checkpoint type: " + id.getClass());
        }
        return new FSCheckpointReadChannel(fs.open(((FSCheckpointID) id).getPath()));
    }

    @Override
    public CheckpointID commit(final CheckpointWriteChannel ch) throws IOException, InterruptedException {
        if (ch.isOpen()) {
            ch.close();
        }
        final FSCheckpointWriteChannel hch = (FSCheckpointWriteChannel) ch;
        final Path dst = hch.getDestination();
        if (!fs.rename(tmpfile(dst), dst)) {
            // attempt to clean up
            abort(ch);
            throw new IOException("Failed to promote checkpoint" + tmpfile(dst) + " -> " + dst);
        }
        return new FSCheckpointID(hch.getDestination());
    }

    @Override
    public void abort(final CheckpointWriteChannel ch) throws IOException {
        if (ch.isOpen()) {
            ch.close();
        }
        final FSCheckpointWriteChannel hch = (FSCheckpointWriteChannel) ch;
        final Path tmp = tmpfile(hch.getDestination());
        try {
            if (!fs.delete(tmp, false)) {
                throw new IOException("Failed to delete checkpoint during abort");
            }
        } catch (FileNotFoundException e) {
            // IGNORE
        }
    }

    @Override
    public boolean delete(final CheckpointID id) throws IOException, InterruptedException {
        if (!(id instanceof FSCheckpointID)) {
            throw new IllegalArgumentException("Mismatched checkpoint type: " + id.getClass());
        }
        Path tmp = ((FSCheckpointID) id).getPath();
        try {
            return fs.delete(tmp, false);
        } catch (FileNotFoundException e) {
            // IGNORE
        }
        return true;
    }

    @NamedParameter(doc = "The path to be used to store the checkpoints.")
    static class PATH implements Name<String> {
    }

    @NamedParameter(doc = "The replication factor to be used for the stored checkpoints", default_value = "3")
    static class REPLICATION_FACTOR implements Name<Short> {
    }

    private static class FSCheckpointWriteChannel implements CheckpointWriteChannel {
        private final Path finalDst;
        private final WritableByteChannel out;
        private boolean isOpen = true;

        FSCheckpointWriteChannel(final Path finalDst, final FSDataOutputStream out) {
            this.finalDst = finalDst;
            this.out = Channels.newChannel(out);
        }

        public int write(final ByteBuffer b) throws IOException {
            return out.write(b);
        }

        public Path getDestination() {
            return finalDst;
        }

        @Override
        public void close() throws IOException {
            isOpen = false;
            out.close();
        }

        @Override
        public boolean isOpen() {
            return isOpen;
        }

    }

    private static class FSCheckpointReadChannel implements CheckpointReadChannel {

        private final ReadableByteChannel in;
        private boolean isOpen = true;

        FSCheckpointReadChannel(final FSDataInputStream in) {
            this.in = Channels.newChannel(in);
        }

        @Override
        public int read(final ByteBuffer bb) throws IOException {
            return in.read(bb);
        }

        @Override
        public void close() throws IOException {
            isOpen = false;
            in.close();
        }

        @Override
        public boolean isOpen() {
            return isOpen;
        }

    }

}