com.github.mrstampy.kitchensync.stream.FileStreamer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of KitchenSync-core Show documentation
Show all versions of KitchenSync-core Show documentation
KitchenSync-core - A Java Library for Distributed Communication
/*
* KitchenSync-core Java Library Copyright (C) 2014 Burton Alexander
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package com.github.mrstampy.kitchensync.stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import com.github.mrstampy.kitchensync.netty.channel.KiSyChannel;
/**
* This implementation of the {@link Streamer} interface streams arbitrarily
* large files to the specified destination. While the same functionality can be
* accomplished using a {@link FileInputStream} with the
* {@link BufferedInputStreamStreamer}, testing has shown this implementation to
* be 5-10% faster at {@link #fullThrottle()}.
*/
public class FileStreamer extends AbstractStreamer {
private MappedByteBuffer mappedByteBuffer;
/**
* The Constructor.
*
* @param file
* the file
* @param channel
* the channel
* @param destination
* the destination
* @throws Exception
* the exception
*/
public FileStreamer(File file, KiSyChannel channel, InetSocketAddress destination) throws Exception {
this(file, channel, destination, DEFAULT_CHUNK_SIZE);
}
/**
* The Constructor.
*
* @param file
* the file
* @param channel
* the channel
* @param destination
* the destination
* @param chunkSize
* the chunk size
* @throws Exception
* the exception
*/
public FileStreamer(File file, KiSyChannel channel, InetSocketAddress destination, int chunkSize) throws Exception {
super(channel, destination, chunkSize);
prepareForSend(file);
}
/*
* (non-Javadoc)
*
* @see com.github.mrstampy.kitchensync.stream.Streamer#remaining()
*/
@Override
public long remaining() {
return mappedByteBuffer.remaining();
}
/*
* (non-Javadoc)
*
* @see com.github.mrstampy.kitchensync.stream.Streamer#reset()
*/
@Override
public void reset() {
resetPosition(0);
complete.set(false);
}
/*
* (non-Javadoc)
*
* @see com.github.mrstampy.kitchensync.stream.Streamer#resetPosition(int)
*/
@Override
public void resetPosition(int newPosition) {
if (streaming.get()) throw new IllegalStateException("Cannot reset position when streaming");
if (newPosition < 0 || newPosition > mappedByteBuffer.limit()) return;
mappedByteBuffer.position(newPosition);
resetSequenceFromPosition(newPosition);
}
/*
* (non-Javadoc)
*
* @see com.github.mrstampy.kitchensync.stream.AbstractStreamer#getChunk()
*/
@Override
protected byte[] getChunk() {
int remaining = (int) remaining();
byte[] chunk = createByteArray(remaining);
mappedByteBuffer.get(chunk);
return chunk;
}
/*
* (non-Javadoc)
*
* @see
* com.github.mrstampy.kitchensync.stream.AbstractStreamer#prepareForSend(
* java.lang.Object)
*/
@Override
protected void prepareForSend(File message) throws IOException {
FileInputStream fis = new FileInputStream(message);
try {
FileChannel fileChannel = fis.getChannel();
mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, 0, fileChannel.size());
setSize(mappedByteBuffer.remaining());
} finally {
fis.close();
}
sent.set(0);
}
}