You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by mh...@apache.org on 2006/11/24 21:20:29 UTC

svn commit: r478981 - in /mina/sandbox/mheath/aioj/trunk: ./ src/ src/main/ src/main/c/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/aio/ src/main/java/org/apache/aio/common/ src/main/java/org/apache/aio/posix/ s...

Author: mheath
Date: Fri Nov 24 12:20:28 2006
New Revision: 478981

URL: http://svn.apache.org/viewvc?view=rev&rev=478981
Log:
Moved from Directory sandbox to Mina sandbox.

Added:
    mina/sandbox/mheath/aioj/trunk/LICENSE.txt
    mina/sandbox/mheath/aioj/trunk/NOTICE.txt
    mina/sandbox/mheath/aioj/trunk/pom.xml
    mina/sandbox/mheath/aioj/trunk/src/
    mina/sandbox/mheath/aioj/trunk/src/main/
    mina/sandbox/mheath/aioj/trunk/src/main/c/
    mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile   (with props)
    mina/sandbox/mheath/aioj/trunk/src/main/c/org_apache_aio.cpp
    mina/sandbox/mheath/aioj/trunk/src/main/java/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFuture.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureBatch.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureListener.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureReadWrite.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AsynchronousFileChannel.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/BatchRequest.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/Operation.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/AbstractAioFuture.java
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/
    mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/PosixAioFutureReadWrite.java
    mina/sandbox/mheath/aioj/trunk/src/test/
    mina/sandbox/mheath/aioj/trunk/src/test/java/
    mina/sandbox/mheath/aioj/trunk/src/test/java/AIOTest.java
    mina/sandbox/mheath/aioj/trunk/target/
    mina/sandbox/mheath/aioj/trunk/target/jni/
    mina/sandbox/mheath/aioj/trunk/target/test-classes/
    mina/sandbox/mheath/aioj/trunk/todo.txt

Added: mina/sandbox/mheath/aioj/trunk/LICENSE.txt
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/LICENSE.txt?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/LICENSE.txt (added)
+++ mina/sandbox/mheath/aioj/trunk/LICENSE.txt Fri Nov 24 12:20:28 2006
@@ -0,0 +1,20 @@
+/*
+ *                           Apache License
+ *                      Version 2.0, January 2004
+ *                   http://www.apache.org/licenses/
+ *
+ *   Copyright 2006 Apache Software Foundation
+ *
+ *   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.
+ *
+ */

Added: mina/sandbox/mheath/aioj/trunk/NOTICE.txt
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/NOTICE.txt?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/NOTICE.txt (added)
+++ mina/sandbox/mheath/aioj/trunk/NOTICE.txt Fri Nov 24 12:20:28 2006
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).

Added: mina/sandbox/mheath/aioj/trunk/pom.xml
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/pom.xml?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/pom.xml (added)
+++ mina/sandbox/mheath/aioj/trunk/pom.xml Fri Nov 24 12:20:28 2006
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.apache.aio</groupId>
+	<artifactId>aio</artifactId>
+	<version>0.1-SNAPSHOT</version>
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>exec-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<!-- this execution happens just after compiling the java classes, and builds the native code. -->
+						<id>build-native</id>
+						<phase>process-classes</phase>
+						<goals>
+							<goal>exec</goal>
+						</goals>
+						<configuration>
+							<executable>src/main/c/Makefile</executable>
+							<workingDirectory>src/main/c</workingDirectory>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+	
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.1</version>
+		</dependency>
+	</dependencies>
+
+</project>

Added: mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile Fri Nov 24 12:20:28 2006
@@ -0,0 +1,33 @@
+#!/usr/bin/make -f
+#
+# Makefile for C code
+#
+
+# C sources to compile
+
+TARGET_DIR := ../../../target
+TARGET := $(TARGET_DIR)/libaioj.so
+
+WORKING_DIR := $(TARGET_DIR)/jni
+
+JAVA_BUILD_DIR := $(TARGET_DIR)/classes
+
+JAVA_HOME ?= /opt/java/jdk
+
+INCLUDES := -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux -I $(WORKING_DIR)
+
+# classpath for javah
+ifdef CLASSPATH
+JAVAH_CLASSPATH = $(JAVA_BUILD_DIR):$(CLASSPATH)
+else
+JAVAH_CLASSPATH = $(JAVA_BUILD_DIR)
+endif
+
+all: $(TARGET)
+
+$(TARGET): org_apache_aio.cpp $(WORKING_DIR)/org_apache_aio_AsynchronousFileChannel.h $(WORKING_DIR)/org_apache_aio_posix_PosixAioFutureReadWrite.h
+	g++ -shared -lrt -lstdc++ $(INCLUDES) org_apache_aio.cpp -o $(TARGET)
+
+$(WORKING_DIR)/org_apache_aio_AsynchronousFileChannel.h $(WORKING_DIR)/org_apache_aio_posix_PosixAioFutureReadWrite.h: $(TARGET_DIR)/classes/org/apache/aio/AsynchronousFileChannel.class $(TARGET_DIR)/classes/org/apache/aio/posix/PosixAioFutureReadWrite.class
+	mkdir -p $(TARGET_DIR)/jni
+	javah -classpath $(JAVAH_CLASSPATH) -d $(WORKING_DIR) org.apache.aio.AsynchronousFileChannel org.apache.aio.posix.PosixAioFutureReadWrite
\ No newline at end of file

Propchange: mina/sandbox/mheath/aioj/trunk/src/main/c/Makefile
------------------------------------------------------------------------------
    svn:executable = *

Added: mina/sandbox/mheath/aioj/trunk/src/main/c/org_apache_aio.cpp
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/c/org_apache_aio.cpp?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/c/org_apache_aio.cpp (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/c/org_apache_aio.cpp Fri Nov 24 12:20:28 2006
@@ -0,0 +1,369 @@
+#include <aio.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "org_apache_aio_AsynchronousFileChannel.h"
+#include "org_apache_aio_posix_PosixAioFutureReadWrite.h"
+
+#define DEBUG 1
+
+static JavaVM *jvm;
+static jclass ioException;
+static jclass nullPointerException;
+
+// --- Classes and IDs for PosixAioFutureReadWrite ---
+static jclass posixAioFutureReadWrite;
+static jmethodID CID_posixAioFutureReadWrite;
+static jmethodID posixAioFutureReadWrite_processFutureListenersID;
+static jfieldID posixAioFutureReadWrite_aiocbPtrID;
+static jfieldID posixAioFutureReadWrite_bufferID;
+
+static jfieldID fdID; // ID for java.io.FileDescriptor.fd
+static jfieldID fieldDescID; // ID for org.apache.aio.AsynchronousFileChannel.fd
+
+static jobject operationRead;
+static jobject operationWrite;
+static jobject operationBatchRead;
+static jobject operationBatchWrite;
+
+extern "C"
+{
+	JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved);
+	JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved);
+	void aio_read_completion_handler(sigval_t sigval);
+	void aio_write_completion_handler(sigval_t sigval);
+}
+
+// --- Utility Functions ----------------------------------------------------
+jint getFD(JNIEnv *env, jobject asynchFileChannel)
+{
+	jobject fieldDesc = env->GetObjectField(asynchFileChannel, fieldDescID);
+	return env->GetIntField(fieldDesc, fdID);
+}
+
+inline jint getBufferPosition(JNIEnv *env, jobject buffer)
+{
+	jclass cls = env->GetObjectClass(buffer);
+	jmethodID MID_position = env->GetMethodID(cls, "position", "()I");
+	return env->CallIntMethod(buffer, MID_position); 
+}
+
+inline void setBufferPosition(JNIEnv *env, jobject buffer, jint position)
+{
+	jclass cls = env->GetObjectClass(buffer);
+	jmethodID MID_position = env->GetMethodID(cls, "position", "(I)Ljava/nio/Buffer;");
+	env->CallVoidMethod(buffer, MID_position, position);
+}
+
+inline jint getBufferLimit(JNIEnv *env, jobject buffer)
+{
+	jclass cls = env->GetObjectClass(buffer);
+	jmethodID MID_limit = env->GetMethodID(cls, "limit", "()I");
+	return env->CallIntMethod(buffer, MID_limit); 
+}
+
+inline void setBufferLimit(JNIEnv *env, jobject buffer, jint limit)
+{
+	jclass cls = env->GetObjectClass(buffer);
+	jmethodID MID_limit = env->GetMethodID(cls, "limit", "(I)Ljava/nio/Buffer;");
+	env->CallVoidMethod(buffer, MID_limit, limit);
+}
+
+jobject createPosixAioFutureReadWrite(JNIEnv *env, jobject channel, jobject operation, void *aiocb, jobject buffer, long position)
+{
+	jvalue values[5];
+	values[0].l = channel;
+	values[1].l = operation;
+	values[2].j = (jlong)aiocb;
+	values[3].l = buffer;
+	values[4].j = position;
+	jobject future = env->NewObjectA(posixAioFutureReadWrite, CID_posixAioFutureReadWrite, values);
+	return env->NewGlobalRef(future);
+}
+
+struct aiocb *setupAioRequest(JNIEnv *env, jobject asynchronousFileChannel, jobject buffer, jlong position, jobject operation)
+{
+		// Get address and capacity of buffer
+	if (buffer == NULL)
+	{
+		env->ThrowNew(nullPointerException, "buffer cannot be null");
+	}
+	// TODO: Add support for non direct byte buffers
+	jbyte *bufferAddress = (jbyte *)env->GetDirectBufferAddress(buffer);
+	if (bufferAddress == NULL)
+	{
+		env->ThrowNew(ioException, "Must use direct ByteBuffer");
+		return NULL;
+	}
+	// Adjust bufferAddress by the position of the buffer
+	jint bufferPosition = getBufferPosition(env, buffer); 
+	bufferAddress += bufferPosition; 
+	jint bufferSize = getBufferLimit(env, buffer) - position;
+
+	// Allocate aiocb
+	struct aiocb *req = (aiocb*)malloc(sizeof(aiocb));
+	bzero(req, sizeof(struct aiocb));
+	
+	jobject future = createPosixAioFutureReadWrite(env, asynchronousFileChannel, operation, req, buffer, position);
+
+	// Setup aiocb
+	req->aio_fildes = getFD(env, asynchronousFileChannel);
+	req->aio_offset = position;
+	req->aio_buf = bufferAddress;
+	req->aio_nbytes = bufferSize;
+	
+	req->aio_sigevent.sigev_notify = SIGEV_THREAD;
+	if (operation == operationRead)
+	{
+		req->aio_sigevent.sigev_notify_function = aio_read_completion_handler;
+	} else if (operation == operationWrite) {
+		req->aio_sigevent.sigev_notify_function = aio_write_completion_handler;
+	}
+	req->aio_sigevent.sigev_notify_attributes = NULL;
+	req->aio_sigevent.sigev_value.sival_ptr = future;
+	
+	return req;
+}
+
+// --- OnLoad and OnUnload Functions ----------------------------------------
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+	jint JNIversion = JNI_VERSION_1_4;
+	if (DEBUG)
+	{
+		fprintf(stdout, "Initializing native code for JNI version 0x%x\n", JNIversion);
+		fflush(stdout);
+	}
+	
+	// Initialize static jvm pointer.
+	jvm = vm;
+	
+	JNIEnv *env;
+	if (vm->GetEnv((void**)&env, JNIversion))
+	{
+		return JNI_ERR;
+	}
+	
+	jclass cls;
+	cls = env->FindClass("java/io/IOException");
+	ioException = (jclass)env->NewWeakGlobalRef(cls);
+	
+	cls = env->FindClass("java/lang/NullPointerException");
+	nullPointerException = (jclass)env->NewWeakGlobalRef(cls);
+	
+	cls = env->FindClass("org/apache/aio/posix/PosixAioFutureReadWrite");
+	posixAioFutureReadWrite = (jclass)env->NewWeakGlobalRef(cls);
+	CID_posixAioFutureReadWrite = env->GetMethodID(posixAioFutureReadWrite, "<init>", "(Lorg/apache/aio/AsynchronousFileChannel;Lorg/apache/aio/Operation;JLjava/nio/ByteBuffer;J)V");
+	posixAioFutureReadWrite_processFutureListenersID = env->GetMethodID(posixAioFutureReadWrite, "processFutureListeners", "()V");
+	posixAioFutureReadWrite_aiocbPtrID = env->GetFieldID(posixAioFutureReadWrite, "aiocbPtr", "J"); 
+	posixAioFutureReadWrite_bufferID = env->GetFieldID(posixAioFutureReadWrite, "buffer", "Ljava/nio/ByteBuffer;");
+	
+	cls = env->FindClass("java/io/FileDescriptor");
+	fdID = env->GetFieldID(cls, "fd", "I");
+	
+	cls = env->FindClass("org/apache/aio/AsynchronousFileChannel");
+	fieldDescID = env->GetFieldID(cls, "fd", "Ljava/io/FileDescriptor;");
+	
+	cls = env->FindClass("org/apache/aio/Operation");
+	jfieldID fid;
+	fid = env->GetStaticFieldID(cls, "READ", "Lorg/apache/aio/Operation;");
+	operationRead = env->NewWeakGlobalRef(env->GetStaticObjectField(cls, fid));
+	fid = env->GetStaticFieldID(cls, "WRITE", "Lorg/apache/aio/Operation;");
+	operationWrite = env->NewWeakGlobalRef(env->GetStaticObjectField(cls, fid));
+	fid = env->GetStaticFieldID(cls, "BATCH_READ", "Lorg/apache/aio/Operation;");
+	operationBatchRead = env->NewWeakGlobalRef(env->GetStaticObjectField(cls, fid));
+	fid = env->GetStaticFieldID(cls, "BATCH_WRITE", "Lorg/apache/aio/Operation;");
+	operationBatchWrite = env->NewWeakGlobalRef(env->GetStaticObjectField(cls, fid));
+	
+	return JNIversion;
+} 
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+	jint JNIversion = JNI_VERSION_1_4;
+	JNIEnv *env;
+	if (vm->GetEnv((void**)&env, JNIversion))
+	{
+		return;
+	}
+	
+	env->DeleteWeakGlobalRef(ioException);
+	env->DeleteWeakGlobalRef(nullPointerException);
+	env->DeleteWeakGlobalRef(posixAioFutureReadWrite);
+	env->DeleteWeakGlobalRef(operationRead);
+	env->DeleteWeakGlobalRef(operationWrite);
+	env->DeleteWeakGlobalRef(operationBatchRead);
+	env->DeleteWeakGlobalRef(operationBatchWrite);
+}
+
+// --- AsynchronousFileChannel method implementations ----------------------
+JNIEXPORT jobject JNICALL Java_org_apache_aio_AsynchronousFileChannel_write
+  (JNIEnv *env, jobject obj, jobject buffer, jlong position)
+{
+	if (DEBUG)
+	{
+		fprintf(stdout, "aio write at file position %d\n", position);
+		fflush(stdout);
+	}
+	struct aiocb *req = setupAioRequest(env, obj, buffer, position, operationWrite);
+	int ret = aio_write(req);
+	if (ret)
+	{
+		// TODO Handle errors from ret
+		// return a null on error.
+		return NULL;
+	}
+	return (jobject)req->aio_sigevent.sigev_value.sival_ptr;
+}
+
+JNIEXPORT jobject JNICALL Java_org_apache_aio_AsynchronousFileChannel_read
+  (JNIEnv *env, jobject obj, jobject buffer, jlong position)
+{
+	if (DEBUG)
+	{
+		fprintf(stdout, "aio read at file position %d\n", position);
+		fflush(stdout);
+	}
+	struct aiocb *req = setupAioRequest(env, obj, buffer, position, operationRead);
+	if (DEBUG)
+	{
+		fprintf(stdout, "Do aio read\n");
+		fflush(stdout);
+	}
+	int ret = aio_read(req);
+	if (ret)
+	{
+		// TODO Handle errors from ret
+		// return a null on error.
+		return NULL;
+	}
+
+	// Return future object	
+	return (jobject)req->aio_sigevent.sigev_value.sival_ptr;
+}
+
+JNIEXPORT jobject JNICALL Java_org_apache_aio_AsynchronousFileChannel_batchRead
+  (JNIEnv *env, jobject obj, jobjectArray batch)
+{
+	printf("batchRead\n");
+	return NULL;
+}
+
+JNIEXPORT jobject JNICALL Java_org_apache_aio_AsynchronousFileChannel_batchWrite
+  (JNIEnv *env, jobject obj, jobjectArray batch)
+{
+	printf("batchWrite\n");
+	return NULL;
+}
+
+JNIEXPORT void JNICALL Java_org_apache_aio_AsynchronousFileChannel_suspend
+  (JNIEnv *env, jobject obj, jobjectArray futures)
+{
+	printf("suspend\n");
+}
+
+// --- PosixAioFutureReadWrite methods ---------------------------------------------------
+JNIEXPORT jboolean JNICALL Java_org_apache_aio_posix_PosixAioFutureReadWrite_cancel
+  (JNIEnv *env, jobject obj)
+{
+	struct aiocb *req = (struct aiocb *)env->GetLongField(obj, posixAioFutureReadWrite_aiocbPtrID);
+	int ret = aio_cancel(req->aio_fildes, req);
+	if (ret == AIO_CANCELED)
+	{
+		free(req);
+		return 1;
+	} 
+	return 0;
+}
+
+// --- Completion handlers ----------------------------------------------------------------
+void aio_read_completion_handler(sigval_t sigval)
+{
+	if (DEBUG)
+	{
+		fprintf(stdout, "In read completion handler\n");
+		fflush(stdout);
+	}
+
+	JNIEnv *env;
+	jint res = jvm->AttachCurrentThread((void**)&env, NULL);
+	if (res < 0)
+	{
+		fprintf(stderr, "Failed to attach JVM to AIO read thread\n");
+		return;
+	}
+	
+	jobject future = (jobject)sigval.sival_ptr;
+	struct aiocb *req = (struct aiocb *)env->GetLongField(future, posixAioFutureReadWrite_aiocbPtrID);
+	
+	/* Did the request complete? */
+	if (aio_error(req) == 0) {
+		/* Request completed successfully, get number of bytes processed */
+		int ret = aio_return( req );
+		
+		// Adjust buffer limit
+		jobject buffer = env->GetObjectField(future, posixAioFutureReadWrite_bufferID);
+		int limit = ret + getBufferPosition(env, buffer);
+		setBufferLimit(env, buffer, limit);
+		
+		// Call aio listeners
+		env->CallVoidMethod(future, posixAioFutureReadWrite_processFutureListenersID);
+		
+		// Free resources		
+		free(req);
+		env->DeleteGlobalRef(future);
+	} else {
+		// TODO Find a way to handle exception here
+		fprintf(stderr, "ERROR: AIO read request did NOT complete\n");
+		fflush(stderr);
+	}
+
+	jvm->DetachCurrentThread();
+	return;
+}
+
+void aio_write_completion_handler(sigval_t sigval)
+{
+	if (DEBUG)
+	{
+		fprintf(stdout, "In write completion handler\n");
+		fflush(stdout);
+	}
+
+	JNIEnv *env;
+	jint res = jvm->AttachCurrentThread((void**)&env, NULL);
+	if (res < 0)
+	{
+		fprintf(stderr, "Failed to attach JVM to AIO write thread\n");
+		return;
+	}
+	
+	jobject future = (jobject)sigval.sival_ptr;
+	struct aiocb *req = (struct aiocb *)env->GetLongField(future, posixAioFutureReadWrite_aiocbPtrID);
+	
+	/* Did the request complete? */
+	if (aio_error(req) == 0) {
+		/* Request completed successfully, get number of bytes processed */
+		int ret = aio_return( req );
+		
+		// Adjust buffer position
+		jobject buffer = env->GetObjectField(future, posixAioFutureReadWrite_bufferID);
+		int position = getBufferPosition(env, buffer) + ret;
+		setBufferPosition(env, buffer, position);
+		
+		// Call aio listeners
+		env->CallVoidMethod(future, posixAioFutureReadWrite_processFutureListenersID);
+		
+		// Free resources		
+		free(req);
+		env->DeleteGlobalRef(future);
+	} else {
+		// TODO Find a way to handle exception here
+		fprintf(stderr, "ERROR: AIO write request did NOT complete\n");
+		fflush(stderr);
+	}
+
+	jvm->DetachCurrentThread();
+	return;
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFuture.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFuture.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFuture.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFuture.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,23 @@
+package org.apache.aio;
+
+import java.util.concurrent.TimeUnit;
+
+public interface AioFuture<T extends AioFuture> {
+
+	public void addListener(AioFutureListener<T> ioFutureListener);
+	
+	public void removeListener(AioFutureListener<T> ioFutureListener);
+	
+	public AsynchronousFileChannel getChannel();
+	
+	public boolean isCompleted();
+	
+	public void join() throws InterruptedException;
+	
+	public boolean join(long timeout, TimeUnit timeUnit) throws InterruptedException;
+	
+	public boolean cancel();
+	
+	public Operation getOperation();
+	
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureBatch.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureBatch.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureBatch.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureBatch.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,10 @@
+package org.apache.aio;
+
+public interface AioFutureBatch extends AioFuture {
+	
+	public void addListener(AioFutureListener<AioFutureBatch> ioFutureListener);
+	
+	public void removeListener(AioFutureListener<AioFutureBatch> ioFutureListener);
+	
+	public BatchRequest[] getRequests();
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureListener.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureListener.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureListener.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureListener.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,7 @@
+package org.apache.aio;
+
+public interface AioFutureListener<T extends AioFuture> {
+
+	public void onCompletion(T ioFuture);
+	
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureReadWrite.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureReadWrite.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureReadWrite.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AioFutureReadWrite.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,11 @@
+package org.apache.aio;
+
+import java.nio.ByteBuffer;
+
+public interface AioFutureReadWrite extends AioFuture<AioFutureReadWrite> {
+
+	public ByteBuffer getBuffer();
+	
+	public long getPosition();
+	
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AsynchronousFileChannel.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AsynchronousFileChannel.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AsynchronousFileChannel.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/AsynchronousFileChannel.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,44 @@
+package org.apache.aio;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class AsynchronousFileChannel {
+
+	static {
+		System.loadLibrary("aioj");
+	}
+
+	private FileDescriptor fd;
+
+	public AsynchronousFileChannel(FileDescriptor fd) throws IOException {
+		if (fd == null) {
+			throw new NullPointerException("fd cannot be null");
+		}
+		SecurityManager sm = System.getSecurityManager();
+		if (sm != null) {
+			sm.checkWrite(fd);
+		}
+		this.fd = fd;
+	}
+	
+	public FileDescriptor getFD() {
+		return fd;
+	}
+	
+	public boolean isOpen() {
+		return fd.valid();
+	}
+	
+	public native AioFutureReadWrite write(ByteBuffer buffer, long position) throws IOException;
+	
+	public native AioFutureReadWrite read(ByteBuffer buffer, long position) throws IOException;
+	
+	public native AioFutureBatch batchRead(BatchRequest... reads) throws IOException;
+	
+	public native AioFutureBatch batchWrite(BatchRequest... writes) throws IOException;
+	
+	public native void suspend(AioFuture... futures) throws IOException;
+	
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/BatchRequest.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/BatchRequest.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/BatchRequest.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/BatchRequest.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,23 @@
+package org.apache.aio;
+
+import java.nio.ByteBuffer;
+
+public class BatchRequest {
+
+	private final long position;
+	private final ByteBuffer buffer;
+	
+	public BatchRequest(long position, ByteBuffer buffer) {
+		this.position = position;
+		this.buffer = buffer;
+	}
+	
+	public ByteBuffer getBuffer() {
+		return buffer;
+	}
+	
+	public long getPosition() {
+		return position;
+	}
+	
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/Operation.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/Operation.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/Operation.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/Operation.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,8 @@
+package org.apache.aio;
+
+public enum Operation {
+	READ,
+	WRITE,
+	BATCH_READ,
+	BATCH_WRITE
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/AbstractAioFuture.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/AbstractAioFuture.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/AbstractAioFuture.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/common/AbstractAioFuture.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,71 @@
+package org.apache.aio.common;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.aio.AioFuture;
+import org.apache.aio.AioFutureListener;
+import org.apache.aio.AsynchronousFileChannel;
+import org.apache.aio.Operation;
+
+public abstract class AbstractAioFuture<T extends AioFuture> implements AioFuture<T> {
+
+	private final AsynchronousFileChannel channel;
+	private final Operation operation;
+	private final List<AioFutureListener<T>> listeners = new LinkedList<AioFutureListener<T>>();
+	private volatile boolean completed = false;
+
+	protected AbstractAioFuture(AsynchronousFileChannel channel, Operation operation) {
+		this.channel = channel;
+		this.operation = operation;
+	}
+
+	@SuppressWarnings("unchecked")
+	public synchronized void addListener(AioFutureListener<T> ioFutureListener) {
+		if (completed) {
+			ioFutureListener.onCompletion((T)this);
+		} else {
+			listeners.add(ioFutureListener);
+		}
+	}
+
+	public AsynchronousFileChannel getChannel() {
+		return channel;
+	}
+
+	public Operation getOperation() {
+		return operation;
+	}
+
+	public boolean isCompleted() {
+		return completed;
+	}
+
+	public synchronized void join() throws InterruptedException {
+		if (!completed) {
+			wait();
+		}
+	}
+
+	public synchronized boolean join(long timeout, TimeUnit timeUnit) throws InterruptedException {
+		if (!completed) {
+			wait(timeUnit.toMillis(timeout));
+		}
+		return isCompleted();
+	}
+
+	public synchronized void removeListener(AioFutureListener<T> ioFutureListener) {
+		listeners.remove(ioFutureListener);
+	}
+
+	@SuppressWarnings("unchecked")
+	protected synchronized void processFutureListeners() {
+		completed = true;
+		notifyAll();
+		for (AioFutureListener<T> listener : listeners) {
+			listener.onCompletion((T)this);
+		}
+	}
+
+}

Added: mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/PosixAioFutureReadWrite.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/PosixAioFutureReadWrite.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/PosixAioFutureReadWrite.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/main/java/org/apache/aio/posix/PosixAioFutureReadWrite.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,35 @@
+package org.apache.aio.posix;
+
+import java.nio.ByteBuffer;
+
+import org.apache.aio.AioFutureReadWrite;
+import org.apache.aio.AsynchronousFileChannel;
+import org.apache.aio.Operation;
+import org.apache.aio.common.AbstractAioFuture;
+
+public class PosixAioFutureReadWrite extends AbstractAioFuture<AioFutureReadWrite> implements AioFutureReadWrite {
+
+	@SuppressWarnings("unused")
+	private final long aiocbPtr; // Used by native code
+	
+	private final ByteBuffer buffer;
+	private final long position;
+	
+	protected PosixAioFutureReadWrite(AsynchronousFileChannel channel, Operation operation, long aiocbPtr, ByteBuffer buffer, long position) {
+		super(channel, operation);
+		this.aiocbPtr = aiocbPtr;
+		this.buffer = buffer;
+		this.position = position;
+	}
+	
+	public ByteBuffer getBuffer() {
+		return buffer;
+	}
+
+	public long getPosition() {
+		return position;
+	}
+
+	public native boolean cancel();
+
+}

Added: mina/sandbox/mheath/aioj/trunk/src/test/java/AIOTest.java
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/src/test/java/AIOTest.java?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/src/test/java/AIOTest.java (added)
+++ mina/sandbox/mheath/aioj/trunk/src/test/java/AIOTest.java Fri Nov 24 12:20:28 2006
@@ -0,0 +1,38 @@
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+
+import org.apache.aio.AioFutureListener;
+import org.apache.aio.AioFutureReadWrite;
+import org.apache.aio.AsynchronousFileChannel;
+
+public class AIOTest {
+
+	public static void main(String[] args) throws Exception {
+		FileInputStream in = new FileInputStream("/etc/passwd");
+
+		AsynchronousFileChannel achannel = new AsynchronousFileChannel(in.getFD());
+		
+		AioFutureListener<AioFutureReadWrite> listener = new AioFutureListener<AioFutureReadWrite>() {
+					public void onCompletion(AioFutureReadWrite ioFuture) {
+						System.out.println("In callback");
+						byte[] data = new byte[ioFuture.getBuffer().limit() - ioFuture.getBuffer().position()];
+						ioFuture.getBuffer().get(data);
+						System.out.println("  Buffer contains: " + new String(data));
+					}
+				};
+		ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
+		AioFutureReadWrite future = achannel.read(buffer, 0);
+		future.addListener(listener);
+		future.join();
+		
+		FileOutputStream out = new FileOutputStream("/tmp/foo");
+		achannel = new AsynchronousFileChannel(out.getFD());
+		buffer.clear();
+		buffer.put("Have a really nice day!\n".getBytes());
+		buffer.flip();
+		future = achannel.write(buffer, 0);
+		System.out.println(future);
+	}
+		
+}

Added: mina/sandbox/mheath/aioj/trunk/todo.txt
URL: http://svn.apache.org/viewvc/mina/sandbox/mheath/aioj/trunk/todo.txt?view=auto&rev=478981
==============================================================================
--- mina/sandbox/mheath/aioj/trunk/todo.txt (added)
+++ mina/sandbox/mheath/aioj/trunk/todo.txt Fri Nov 24 12:20:28 2006
@@ -0,0 +1,7 @@
+- Add support for heap buffers
+- Throw IO Exceptions when aio calls return an error
+- Figure out batch requests
+
+=== Testing ===
+- Make sure the AsynchronousFileChannel can be unloaded without holding onto native references
+- Test for memory leaks
\ No newline at end of file