eu.stratosphere.nephele.services.iomanager.ChannelAccess Maven / Gradle / Ivy
/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* Licensed 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 eu.stratosphere.nephele.services.iomanager;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
/**
* A base class for readers and writers that read data from I/O manager channels, or write data to them.
* Requests handled by channels that inherit from this class are executed asynchronously, which allows
* write-behind for writers and pre-fetching for readers.
*
*
* @param The buffer type used for the underlying IO operations.
*/
public abstract class ChannelAccess
{
/**
* The ID of the underlying channel.
*/
protected final Channel.ID id;
/**
* A file channel for NIO access to the file.
*/
protected final FileChannel fileChannel;
/**
* A request queue for submitting asynchronous requests to the corresponding
* IO worker thread.
*/
protected final RequestQueue requestQueue;
/**
* An exception that was encountered by the asynchronous request handling thread.
*/
protected volatile IOException exception;
// --------------------------------------------------------------------------------------------
/**
* Creates a new channel to the path indicated by the given ID. The channel hands IO requests to
* the given request queue to be processed.
*
* @param channelID The id describing the path of the file that the channel accessed.
* @param requestQueue The queue that this channel hands its IO requests to.
* @param writeEnabled Flag describing whether the channel should be opened in read/write mode, rather
* than in read-only mode.
* @throws IOException Thrown, if the channel could no be opened.
*/
protected ChannelAccess(Channel.ID channelID, RequestQueue requestQueue, boolean writeEnabled)
throws IOException
{
if (channelID == null || requestQueue == null) {
throw new NullPointerException();
}
this.id = channelID;
this.requestQueue = requestQueue;
try {
RandomAccessFile file = new RandomAccessFile(id.getPath(), writeEnabled ? "rw" : "r");
this.fileChannel = file.getChannel();
}
catch (IOException e) {
throw new IOException("Channel to path '" + channelID.getPath() + "' could not be opened.", e);
}
}
// --------------------------------------------------------------------------------------------
/**
* Checks, whether this channel has been closed;
*
* @return True, if the channel has been closed, false otherwise.
*/
public abstract boolean isClosed();
/**
* This method is invoked by the asynchronous I/O thread to return a buffer after the I/O request
* completed.
*
* @param buffer The buffer to be returned.
*/
protected abstract void returnBuffer(T buffer);
// --------------------------------------------------------------------------------------------
/**
* Gets the channel ID of this channel.
*
* @return This channel's ID.
*/
public final Channel.ID getChannelID()
{
return this.id;
}
/**
* Checks the exception state of this channel. The channel is erroneous, if one of its requests could not
* be processed correctly.
*
* @throws IOException Thrown, if the channel is erroneous. The thrown exception contains the original exception
* that defined the erroneous state as its cause.
*/
public final void checkErroneous() throws IOException
{
if (this.exception != null) {
throw new IOException("The channel is erroneous.", this.exception);
}
}
/**
* Deletes this channel by physically removing the file beneath it.
* This method may only be called on a closed channel.
*/
public void deleteChannel()
{
if (this.fileChannel.isOpen()) {
throw new IllegalStateException("Cannot delete a channel that is open.");
}
// make a best effort to delete the file. Don't report exceptions.
try {
File f = new File(this.id.getPath());
if (f.exists()) {
f.delete();
}
} catch (Throwable t) {}
}
/**
* Handles a processed Buffer. This method is invoked by the
* asynchronous IO worker threads upon completion of the IO request with the
* provided buffer and/or an exception that occurred while processing the request
* for that buffer.
*
* @param buffer The buffer to be processed.
* @param ex The exception that occurred in the I/O threads when processing the buffer's request.
*/
final void handleProcessedBuffer(T buffer, IOException ex) {
if (ex != null && this.exception == null) {
this.exception = ex;
}
returnBuffer(buffer);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy