alluxio.worker.netty.UnderFileSystemDataServerHandler.java Source code

Java tutorial

Introduction

Here is the source code for alluxio.worker.netty.UnderFileSystemDataServerHandler.java

Source

/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.worker.netty;

import alluxio.Constants;
import alluxio.network.protocol.RPCFileReadRequest;
import alluxio.network.protocol.RPCFileReadResponse;
import alluxio.network.protocol.RPCFileWriteRequest;
import alluxio.network.protocol.RPCFileWriteResponse;
import alluxio.network.protocol.RPCResponse;
import alluxio.network.protocol.databuffer.DataBuffer;
import alluxio.network.protocol.databuffer.DataByteBuffer;
import alluxio.worker.file.FileSystemWorker;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

import javax.annotation.concurrent.NotThreadSafe;

/**
 * This class handles filesystem data server requests.
 */
@NotThreadSafe
final class UnderFileSystemDataServerHandler {
    private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE);

    /** Filesystem worker which handles file level operations for the worker. */
    private final FileSystemWorker mWorker;

    /**
     * Constructs a file data server handler for serving any ufs read/write requests.
     *
     * @param worker the file system worker
     */
    public UnderFileSystemDataServerHandler(FileSystemWorker worker) {
        mWorker = worker;
    }

    /**
     * Handles a {@link RPCFileReadRequest} by reading the data through an input stream provided by
     * the file worker. This method assumes the length to read is less than or equal to the unread
     * data in the file.
     *
     * @param ctx The context of this request which handles the result of this operation
     * @param req The initiating {@link RPCFileReadRequest}
     * @throws IOException if an I/O error occurs when interacting with the UFS
     */
    public void handleFileReadRequest(ChannelHandlerContext ctx, RPCFileReadRequest req) throws IOException {
        req.validate();

        long ufsFileId = req.getTempUfsFileId();
        long offset = req.getOffset();
        long length = req.getLength();
        byte[] data = new byte[(int) length];

        try {
            InputStream in = mWorker.getUfsInputStream(ufsFileId, offset);
            int bytesRead = 0;
            if (in != null) { // if we have not reached the end of the file
                while (bytesRead < length) {
                    int read = in.read(data, bytesRead, (int) length - bytesRead);
                    if (read == -1) {
                        break;
                    }
                    bytesRead += read;
                }
            }
            DataBuffer buf = bytesRead != 0 ? new DataByteBuffer(ByteBuffer.wrap(data, 0, bytesRead), bytesRead)
                    : null;
            RPCFileReadResponse resp = new RPCFileReadResponse(ufsFileId, offset, bytesRead, buf,
                    RPCResponse.Status.SUCCESS);
            ChannelFuture future = ctx.writeAndFlush(resp);
            future.addListener(ChannelFutureListener.CLOSE);
        } catch (Exception e) {
            LOG.error("Failed to read ufs file, may have been closed due to a client timeout.", e);
            RPCFileReadResponse resp = RPCFileReadResponse.createErrorResponse(req,
                    RPCResponse.Status.UFS_READ_FAILED);
            ChannelFuture future = ctx.writeAndFlush(resp);
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * Handles a {@link RPCFileWriteRequest} by writing the data through an output stream provided
     * by the file worker. This method only allows appending data to the file and does not support
     * writing at arbitrary offsets.
     *
     * @param ctx The context of this request which handles the result of this operation
     * @param req The initiating {@link RPCFileWriteRequest}
     * @throws IOException if an I/O error occurs when interacting with the UFS
     */
    public void handleFileWriteRequest(ChannelHandlerContext ctx, RPCFileWriteRequest req) throws IOException {
        long ufsFileId = req.getTempUfsFileId();
        // Currently unused as only sequential write is supported
        long offset = req.getOffset();
        long length = req.getLength();
        final DataBuffer data = req.getPayloadDataBuffer();

        try {
            OutputStream out = mWorker.getUfsOutputStream(ufsFileId);
            // This channel will not be closed because the underlying stream should not be closed, the
            // channel will be cleaned up when the underlying stream is closed.
            WritableByteChannel channel = Channels.newChannel(out);
            channel.write(data.getReadOnlyByteBuffer());
            RPCFileWriteResponse resp = new RPCFileWriteResponse(ufsFileId, offset, length,
                    RPCResponse.Status.SUCCESS);
            ChannelFuture future = ctx.writeAndFlush(resp);
            future.addListener(ChannelFutureListener.CLOSE);
        } catch (Exception e) {
            LOG.error("Failed to write ufs file.", e);
            RPCFileWriteResponse resp = RPCFileWriteResponse.createErrorResponse(req,
                    RPCResponse.Status.UFS_WRITE_FAILED);
            ChannelFuture future = ctx.writeAndFlush(resp);
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }
}