All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mrstampy.kitchensync.stream.Streamer Maven / Gradle / Ivy

The newest version!
/*
 * 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 io.netty.channel.ChannelFuture;

import java.net.InetSocketAddress;

import com.github.mrstampy.kitchensync.message.inbound.KiSyInboundMesssageHandler;
import com.github.mrstampy.kitchensync.netty.channel.KiSyChannel;
import com.github.mrstampy.kitchensync.stream.footer.Footer;
import com.github.mrstampy.kitchensync.stream.header.ChunkProcessor;
import com.github.mrstampy.kitchensync.stream.header.NoProcessChunkProcessor;
import com.github.mrstampy.kitchensync.stream.inbound.StreamAckInboundMessageHandler;

/**
 * The Interface Streamer defines the methods to stream data to a remote socket
 * in chunks. The default size for chunks is {@value #DEFAULT_CHUNK_SIZE} bytes.
 * Three modes of streaming are supported: {@link #fullThrottle()} (default),
 * {@link #ackRequired()} and {@link #setChunksPerSecond(int)}.
 * {@link #setConcurrentThreads(int)} will set the number of concurrent chunks
 * being sent at any one time.
 *
 * @param 
 *          the generic type
 */
public interface Streamer {

	/** The Constant DEFAULT_CHUNK_SIZE, 2048. */
	public static final int DEFAULT_CHUNK_SIZE = 2048;

	/** Value 2, the default number of concurrent message threads. */
	public static final int DEFAULT_CONCURRENT_THREADS = 2;

	/**
	 * Resets the position in the stream for sending. If invoked while streaming
	 * an {@link IllegalStateException} will be thrown.
	 *
	 * @param newPosition
	 *          the new position
	 */
	void resetPosition(int newPosition);

	/**
	 * Streams the message. The message must be set either in the implementation's
	 * constructor or via the {@link #stream(Object)} method. Will throw an
	 * {@link IllegalStateException} if {@link #isComplete()}.
	 *
	 * @return the channel future
	 */
	ChannelFuture stream();

	/**
	 * Sets the message for streaming and invokes {@link #stream()}.
	 *
	 * @param message
	 *          the message
	 * @return the channel future
	 * @throws Exception
	 *           the exception
	 */
	ChannelFuture stream(MSG message) throws Exception;

	/**
	 * Pauses streaming. Streaming is unpaused when {@link #stream()} is invoked.
	 * If already paused this method will do nothing.
	 */
	void pause();

	/**
	 * Returns the size of the message for streaming.
	 *
	 * @return the long
	 */
	long size();

	/**
	 * Returns the number of bytes left for streaming.
	 *
	 * @return the long
	 */
	long remaining();

	/**
	 * Returns the number of bytes streamed for the message.
	 *
	 * @return the long
	 */
	long sent();

	/**
	 * This method will return true when the current message has been completely
	 * sent, failed with an error or streaming has been cancelled. Further state
	 * information can be obtained from the ChannelFuture associated with the
	 * streaming ({@link #getFuture()}).
	 * 
	 * @return true if complete
	 * @see #getFuture()
	 */
	boolean isComplete();

	/**
	 * Returns true if the Streamer is currently streaming.
	 * 
	 * @return true if streaming
	 */
	boolean isStreaming();

	/**
	 * Gets the future.
	 *
	 * @return the future
	 */
	ChannelFuture getFuture();

	/**
	 * Gets the channel.
	 *
	 * @return the channel
	 */
	KiSyChannel getChannel();

	/**
	 * Sets the channel.
	 *
	 * @param channel
	 *          the channel
	 */
	void setChannel(KiSyChannel channel);

	/**
	 * Returns the size of chunks for streaming.
	 *
	 * @return the chunk size
	 */
	int getChunkSize();

	/**
	 * Sets the chunk size. For best performance when at full throttle the value
	 * should be a power of two.
	 *
	 * @param chunkSize
	 *          the chunk size
	 */
	void setChunkSize(int chunkSize);

	/**
	 * Gets the destination.
	 *
	 * @return the destination
	 */
	InetSocketAddress getDestination();

	/**
	 * Sets the destination.
	 *
	 * @param destination
	 *          the destination
	 */
	void setDestination(InetSocketAddress destination);

	/**
	 * Cancels streaming and {@link #reset()}s.
	 */
	void cancel();

	/**
	 * Resets the position to the start of the message. Will throw an
	 * {@link IllegalStateException} should the message be streaming.
	 */
	void reset();

	/**
	 * Resets the position to the specified sequence, if possible.
	 *
	 * @param sequence
	 *          the sequence
	 */
	void resetSequence(long sequence);

	/**
	 * If this method is invoked prior to either {@link #stream()} or
	 * {@link #stream(Object)} then the message will be sent at the specified
	 * rate. Throws an {@link IllegalStateException} if already streaming.
*
* * During testing some packet loss occurs for values > 1000. If message * fidelity is a top priority then {@link #ackRequired()} is more suitable.
*
* * Note that this value is multiplicative with {@link #getConcurrentThreads()} * , so that at each sending {@link #getConcurrentThreads()} chunks are sent. * * @param chunksPerSecond * the chunks per second * @see #fullThrottle() * @see #ackRequired() */ void setChunksPerSecond(int chunksPerSecond); /** * Returns the number of chunks to send per second. Will return -1 if either * {@link #fullThrottle()} or {@link #ackRequired()} has been previously * invoked. * * @return the chunks per second */ int getChunksPerSecond(); /** * Returns true if the value of {@link #getChunksPerSecond()} is greater than * zero. * * @return true if the mode is chunks per second * @see #isAckRequired() * @see #isFullThrottle() */ boolean isChunksPerSecond(); /** * If this method is invoked prior to either {@link #stream()} or * {@link #stream(Object)} then the message will be sent at the maximum speed * possible. This is the default streaming type. Throws an * {@link IllegalStateException} if already streaming.
*
* * Packet loss can be expected when at full throttle, on the order of 0.05% * using packets of 2048 bytes. If message fidelity is a top priority then * {@link #ackRequired()} is more suitable.
*
* * Throughput at full throttle on a single host using 2048 byte packets is on * the order of 70 megabytes/sec. * * @see #setChunksPerSecond(int) * @see #ackRequired() */ void fullThrottle(); /** * Returns true if the streamer is running at full throttle. * * @return true, if is full throttle */ boolean isFullThrottle(); /** * If this method is invoked prior to either {@link #stream()} or * {@link #stream(Object)} then each chunk sent will require an * acknowledgement consisting of the sum of the bytes in the sent chunk. If an * acknowledgement has not been received within 10 seconds the last chunk is * resent, continuing to do so until {@link #ackReceived(long)} or the * streaming is {@link #cancel()}led. Throws an {@link IllegalStateException} * if already streaming.
*
* * If speed is a top priority then one of {@link #fullThrottle()} or * {@link #setChunksPerSecond(int)} is more appropriate. And this probably * isn't a good fit for {@link KiSyChannel#isMulticastChannel()}s...
*
* * Throughput on a single host using 2048 byte packets is on the order of 40 * megabytes/sec using 5 concurrent threads. * * @see #ackReceived(long) * @see #fullThrottle() * @see #setChunksPerSecond(int) * @see StreamAckInboundMessageHandler */ void ackRequired(); /** * Returns true if acknowledgement is required for each chunk sent. * * @return true, if is ack required * @see #ackRequired() */ boolean isAckRequired(); /** * This method is to be invoked when {@link #isAckRequired()}. The receiver * will send an acknowledgement consisting of the sum of the bytes in the * chunk received. This method should be invoked by a * {@link KiSyInboundMesssageHandler} on the sender-side. If this method is * not invoked when {@link #isAckRequired()} then the same chunk will be * streamed every second - probably not desired behaviour. * * @param sumOfBytesInChunk * the sum of bytes in chunk * @see StreamerAckRegister#convertToLong(byte[]) */ void ackReceived(long sumOfBytesInChunk); /** * Set the number of concurrent message threads. * * @param concurrentThreads * the number of concurrent message threads */ void setConcurrentThreads(int concurrentThreads); /** * Returns the number of concurrent message threads. * * @return the number of threads */ int getConcurrentThreads(); /** * Gets the current chunk number. * * @return the sequence */ long getSequence(); /** * If true then the {@link #getChunkProcessor()} is used to process each chunk * acquired. {@link NoProcessChunkProcessor} is provided for convenience when * this value is false. * * @return true if {@link #getChunkProcessor()} is invoked for each chunk * acquired. */ boolean isProcessChunk(); /** * Set to true to use {@link #getChunkProcessor()} to process each chunk. * * @param processChunk * true if {@link #getChunkProcessor()} is invoked for each chunk * acquired. */ void setProcessChunk(boolean processChunk); /** * Returns the {@link ChunkProcessor} used when {@link #isProcessChunk()}. * * @return the {@link ChunkProcessor} used if {@link #isProcessChunk()}. */ ChunkProcessor getChunkProcessor(); /** * Sets the {@link ChunkProcessor} used when {@link #isProcessChunk()}. * * @param chunkProcessor * to use if {@link #isProcessChunk()}. */ void setChunkProcessor(ChunkProcessor chunkProcessor); /** * If true then an end of message message will be sent upon completion of * streaming. Defaults to false. * * @return true, if checks if is eom on finish * @see #getFooter() */ boolean isEomOnFinish(); /** * Set to true to send an end of message message upon completion of streaming. * * @param eomOnFinish * the eom on finish * @see #getFooter() */ void setEomOnFinish(boolean eomOnFinish); /** * Returns the {@link Footer} used when {@link #isEomOnFinish()}. * * @return the {@link Footer} to use when {@link #isEomOnFinish()}. */ Footer getFooter(); /** * Sets the {@link Footer} to use when {@link #isEomOnFinish()}. * * @param footer * used when {@link #isEomOnFinish()}. */ void setFooter(Footer footer); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy