com.facebook.infrastructure.net.io.ContentStreamState.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.infrastructure.net.io.ContentStreamState.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 com.facebook.infrastructure.net.io;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.io.*;

import org.apache.log4j.Logger;
import org.apache.commons.lang.ArrayUtils;

import com.facebook.infrastructure.db.Table;

/**
 * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
 */

class ContentStreamState extends StartState {
    private static Logger logger_ = Logger.getLogger(ContentStreamState.class);
    private static long count_ = 64 * 1024 * 1024;
    /* Return this byte array to exit event loop */
    private static byte[] bytes_ = new byte[1];
    private long bytesRead_ = 0L;
    private FileChannel fc_;
    private StreamContextManager.StreamContext streamContext_;
    private StreamContextManager.StreamStatus streamStatus_;

    ContentStreamState(TcpReader stream) {
        super(stream);
        SocketChannel socketChannel = stream.getStream();
        InetSocketAddress remoteAddress = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
        String remoteHost = remoteAddress.getHostName();
        streamContext_ = StreamContextManager.getStreamContext(remoteHost);
        streamStatus_ = StreamContextManager.getStreamStatus(remoteHost);
    }

    private void createFileChannel() throws IOException {
        if (fc_ == null) {
            logger_.debug("Creating file for " + streamContext_.getTargetFile());
            FileOutputStream fos = new FileOutputStream(streamContext_.getTargetFile(), true);
            fc_ = fos.getChannel();
        }
    }

    public byte[] read() throws IOException, ReadNotCompleteException {
        SocketChannel socketChannel = stream_.getStream();
        InetSocketAddress remoteAddress = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
        String remoteHost = remoteAddress.getHostName();
        createFileChannel();
        if (streamContext_ != null) {
            try {
                bytesRead_ += fc_.transferFrom(socketChannel, bytesRead_, ContentStreamState.count_);
                if (bytesRead_ != streamContext_.getExpectedBytes())
                    throw new ReadNotCompleteException(
                            "Specified number of bytes have not been read from the Socket Channel");
            } catch (IOException ex) {
                /* Ask the source node to re-stream this file. */
                streamStatus_.setAction(StreamContextManager.StreamCompletionAction.STREAM);
                handleStreamCompletion(remoteHost);
                /* Delete the orphaned file. */
                File file = new File(streamContext_.getTargetFile());
                file.delete();
                throw ex;
            }
            if (bytesRead_ == streamContext_.getExpectedBytes()) {
                logger_.debug("Removing stream context " + streamContext_);
                handleStreamCompletion(remoteHost);
                bytesRead_ = 0L;
                fc_.close();
                morphState();
            }
        }

        return ArrayUtils.EMPTY_BYTE_ARRAY;
    }

    private void handleStreamCompletion(String remoteHost) throws IOException {
        /* 
         * Streaming is complete. If all the data that has to be received inform the sender via 
         * the stream completion callback so that the source may perform the requisite cleanup. 
        */
        IStreamComplete streamComplete = StreamContextManager.getStreamCompletionHandler(remoteHost);
        if (streamComplete != null) {
            streamComplete.onStreamCompletion(remoteHost, streamContext_, streamStatus_);
        }
    }

    public void morphState() throws IOException {
        /* We instantiate an array of size 1 so that we can exit the event loop of the read. */
        StartState nextState = stream_.getSocketState(TcpReader.TcpReaderState.DONE);
        if (nextState == null) {
            nextState = new DoneState(stream_, ContentStreamState.bytes_);
            stream_.putSocketState(TcpReader.TcpReaderState.DONE, nextState);
        } else {
            nextState.setContextData(ContentStreamState.bytes_);
        }
        stream_.morphState(nextState);
    }

    public void setContextData(Object data) {
        throw new UnsupportedOperationException("This method is not supported in the ContentStreamState");
    }
}