mirror of
https://github.com/openRuyi-Project/gcc.git
synced 2026-10-16 01:17:53 +00:00
2006-08-14 Mark Wielaard <mark@klomp.org> Imported GNU Classpath 0.92 * HACKING: Add more importing hints. Update automake version requirement. * configure.ac (gconf-peer): New enable AC argument. Add --disable-gconf-peer and --enable-default-preferences-peer to classpath configure when gconf is disabled. * scripts/makemake.tcl: Set gnu/java/util/prefs/gconf and gnu/java/awt/dnd/peer/gtk to bc. Classify gnu/java/security/Configuration.java as generated source file. * gnu/java/lang/management/VMGarbageCollectorMXBeanImpl.java, gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java, gnu/java/lang/management/VMClassLoadingMXBeanImpl.java, gnu/java/lang/management/VMRuntimeMXBeanImpl.java, gnu/java/lang/management/VMMemoryManagerMXBeanImpl.java, gnu/java/lang/management/VMThreadMXBeanImpl.java, gnu/java/lang/management/VMMemoryMXBeanImpl.java, gnu/java/lang/management/VMCompilationMXBeanImpl.java: New VM stub classes. * java/lang/management/VMManagementFactory.java: Likewise. * java/net/VMURLConnection.java: Likewise. * gnu/java/nio/VMChannel.java: Likewise. * java/lang/Thread.java (getState): Add stub implementation. * java/lang/Class.java (isEnum): Likewise. * java/lang/Class.h (isEnum): Likewise. * gnu/awt/xlib/XToolkit.java (getClasspathTextLayoutPeer): Removed. * javax/naming/spi/NamingManager.java: New override for StackWalker functionality. * configure, sources.am, Makefile.in, gcj/Makefile.in, include/Makefile.in, testsuite/Makefile.in: Regenerated. From-SVN: r116139
526 lines
14 KiB
C
526 lines
14 KiB
C
/* gnu_java_nio_VMChannel.c -
|
|
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Classpath.
|
|
|
|
GNU Classpath 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, or (at your option)
|
|
any later version.
|
|
|
|
GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301 USA.
|
|
|
|
Linking this library statically or dynamically with other modules is
|
|
making a combined work based on this library. Thus, the terms and
|
|
conditions of the GNU General Public License cover the whole
|
|
combination.
|
|
|
|
As a special exception, the copyright holders of this library give you
|
|
permission to link this library with independent modules to produce an
|
|
executable, regardless of the license terms of these independent
|
|
modules, and to copy and distribute the resulting executable under
|
|
terms of your choice, provided that you also meet, for each linked
|
|
independent module, the terms and conditions of the license of that
|
|
module. An independent module is a module which is not derived from
|
|
or based on this library. If you modify this library, you may extend
|
|
this exception to your version of the library, but you are not
|
|
obligated to do so. If you do not wish to do so, delete this
|
|
exception statement from your version. */
|
|
|
|
|
|
#include <config.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <sys/uio.h>
|
|
#include <string.h>
|
|
|
|
#include <jni.h>
|
|
#include <jcl.h>
|
|
|
|
#include "gnu_java_nio_VMChannel.h"
|
|
|
|
#ifdef HAVE_FCNTL_H
|
|
#include <fcntl.h>
|
|
#endif /* HAVE_FCNTL_H */
|
|
|
|
#define IO_EXCEPTION "java/io/IOException"
|
|
#define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException"
|
|
#define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException"
|
|
|
|
/*
|
|
* Limit to maximum of 16 buffers
|
|
*/
|
|
#define JCL_IOV_MAX 16
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
enum JCL_buffer_type { DIRECT, ARRAY, UNKNOWN };
|
|
|
|
struct JCL_buffer
|
|
{
|
|
enum JCL_buffer_type type;
|
|
jbyte *ptr;
|
|
jint offset;
|
|
jint position;
|
|
jint limit;
|
|
jint count;
|
|
};
|
|
|
|
jmethodID get_method_id(JNIEnv *, jclass, const char *, const char *);
|
|
void JCL_print_buffer(JNIEnv *, struct JCL_buffer *);
|
|
int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject);
|
|
void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint);
|
|
void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong);
|
|
|
|
static jfieldID address_fid;
|
|
static jmethodID get_position_mid;
|
|
static jmethodID set_position_mid;
|
|
static jmethodID get_limit_mid;
|
|
static jmethodID set_limit_mid;
|
|
static jmethodID has_array_mid;
|
|
static jmethodID array_mid;
|
|
static jmethodID array_offset_mid;
|
|
|
|
jmethodID
|
|
get_method_id(JNIEnv *env, jclass clazz, const char *name,
|
|
const char *sig)
|
|
{
|
|
jmethodID mid = (*env)->GetMethodID(env, clazz, name, sig);
|
|
if (mid == NULL)
|
|
{
|
|
JCL_ThrowException(env, "java/lang/InternalError", name);
|
|
return NULL;
|
|
}
|
|
|
|
return mid;
|
|
}
|
|
|
|
void
|
|
JCL_print_buffer(JNIEnv *env __attribute__((__unused__)), struct JCL_buffer *buf)
|
|
{
|
|
fprintf(stdout, "Buffer - type: %d, ptr: %p\n", buf->type, buf->ptr);
|
|
fflush(stdout);
|
|
}
|
|
|
|
|
|
int
|
|
JCL_init_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf)
|
|
{
|
|
jobject address = (*env)->GetObjectField(env, bbuf, address_fid);
|
|
|
|
buf->position = (*env)->CallIntMethod(env, bbuf, get_position_mid);
|
|
buf->limit = (*env)->CallIntMethod(env, bbuf, get_limit_mid);
|
|
buf->offset = 0;
|
|
buf->count = 0;
|
|
buf->type = UNKNOWN;
|
|
|
|
if (address != NULL)
|
|
{
|
|
buf->ptr = (jbyte *) JCL_GetRawData(env, address);
|
|
buf->type = DIRECT;
|
|
(*env)->DeleteLocalRef(env, address);
|
|
}
|
|
else
|
|
{
|
|
jboolean has_array;
|
|
has_array = (*env)->CallBooleanMethod(env, bbuf, has_array_mid);
|
|
|
|
if (has_array == JNI_TRUE)
|
|
{
|
|
jbyteArray arr;
|
|
buf->offset = (*env)->CallIntMethod(env, bbuf, array_offset_mid);
|
|
arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
|
|
buf->ptr = (*env)->GetByteArrayElements(env, arr, 0);
|
|
buf->type = ARRAY;
|
|
(*env)->DeleteLocalRef(env, arr);
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
JCL_release_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf,
|
|
jint action)
|
|
{
|
|
jbyteArray arr;
|
|
|
|
/* Set the position to the appropriate value */
|
|
if (buf->count > 0)
|
|
{
|
|
jobject bbufTemp;
|
|
bbufTemp = (*env)->CallObjectMethod(env, bbuf, set_position_mid,
|
|
buf->position + buf->count);
|
|
(*env)->DeleteLocalRef(env, bbufTemp);
|
|
}
|
|
|
|
switch (buf->type)
|
|
{
|
|
case DIRECT:
|
|
break;
|
|
case ARRAY:
|
|
arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
|
|
(*env)->ReleaseByteArrayElements(env, arr, buf->ptr, action);
|
|
(*env)->DeleteLocalRef(env, arr);
|
|
break;
|
|
case UNKNOWN:
|
|
/* TODO: Handle buffers that are not direct or array backed */
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
JCL_cleanup_buffers(JNIEnv *env,
|
|
struct JCL_buffer *bi_list,
|
|
jint vec_len,
|
|
jobjectArray bbufs,
|
|
jint offset,
|
|
jlong num_bytes)
|
|
{
|
|
jint i;
|
|
|
|
/* Update all of the bbufs with the approriate information */
|
|
for (i = 0; i < vec_len; i++)
|
|
{
|
|
struct JCL_buffer* buf;
|
|
jobject bbuf;
|
|
|
|
buf = &bi_list[i];
|
|
bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
|
|
|
|
if (num_bytes > (buf->limit - buf->position))
|
|
buf->count = (buf->limit - buf->position);
|
|
else
|
|
buf->count = num_bytes;
|
|
|
|
num_bytes -= buf->count;
|
|
|
|
JCL_release_buffer(env, buf, bbuf, JNI_ABORT);
|
|
(*env)->DeleteLocalRef(env, bbuf);
|
|
}
|
|
}
|
|
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env,
|
|
jclass clazz __attribute__ ((__unused__)))
|
|
{
|
|
jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer");
|
|
jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer");
|
|
|
|
address_fid = (*env)->GetFieldID(env, bufferClass, "address",
|
|
"Lgnu/classpath/Pointer;");
|
|
if (address_fid == NULL)
|
|
{
|
|
JCL_ThrowException(env, "java/lang/InternalError",
|
|
"Unable to find internal field");
|
|
return;
|
|
}
|
|
|
|
get_position_mid = get_method_id(env, bufferClass, "position", "()I");
|
|
set_position_mid = get_method_id(env, bufferClass, "position",
|
|
"(I)Ljava/nio/Buffer;");
|
|
get_limit_mid = get_method_id(env, bufferClass, "limit", "()I");
|
|
set_limit_mid = get_method_id(env, bufferClass, "limit",
|
|
"(I)Ljava/nio/Buffer;");
|
|
has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z");
|
|
array_mid = get_method_id(env, byteBufferClass, "array", "()[B");
|
|
array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I");
|
|
}
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env,
|
|
jobject o __attribute__ ((__unused__)),
|
|
jint fd,
|
|
jboolean blocking)
|
|
{
|
|
int opts;
|
|
|
|
opts = fcntl(fd, F_GETFL);
|
|
if (opts < 0)
|
|
{
|
|
JCL_ThrowException(env, IO_EXCEPTION,
|
|
"Failed to get flags for file desriptor");
|
|
return;
|
|
}
|
|
|
|
if (blocking)
|
|
opts |= O_NONBLOCK;
|
|
else
|
|
opts &= ~(O_NONBLOCK);
|
|
|
|
opts = fcntl(fd, F_SETFL, opts);
|
|
|
|
if (opts < 0)
|
|
{
|
|
JCL_ThrowException(env, IO_EXCEPTION,
|
|
"Failed to set flags for file desriptor");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_gnu_java_nio_VMChannel_read (JNIEnv *env,
|
|
jobject o __attribute__ ((__unused__)),
|
|
jint fd,
|
|
jobject bbuf)
|
|
{
|
|
jint len;
|
|
ssize_t result;
|
|
struct JCL_buffer buf;
|
|
|
|
if (JCL_init_buffer(env, &buf, bbuf) < 0)
|
|
{
|
|
/* TODO: Rethrown exception */
|
|
JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
|
|
return -1;
|
|
}
|
|
|
|
len = buf.limit - buf.position;
|
|
|
|
result = read(fd, &(buf.ptr[buf.position + buf.offset]), len);
|
|
buf.count = result;
|
|
|
|
if (result == 0)
|
|
result = -1; /* End Of File */
|
|
else if (result == -1)
|
|
{
|
|
buf.count = 0;
|
|
if (errno == EAGAIN) /* Non-blocking */
|
|
result = 0;
|
|
else if (errno == EBADF) /* Bad fd */
|
|
{
|
|
JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
|
|
JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
|
|
strerror(errno));
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
|
|
JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
|
|
JCL_release_buffer(env, &buf, bbuf, JNI_COMMIT);
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_gnu_java_nio_VMChannel_write (JNIEnv *env,
|
|
jobject o __attribute__ ((__unused__)),
|
|
jint fd,
|
|
jobject bbuf)
|
|
{
|
|
jint len;
|
|
ssize_t result;
|
|
struct JCL_buffer buf;
|
|
|
|
if (JCL_init_buffer(env, &buf, bbuf) < 0)
|
|
{
|
|
/* TODO: Rethrown exception */
|
|
JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
|
|
return -1;
|
|
}
|
|
|
|
len = buf.limit - buf.position;
|
|
|
|
result = write(fd, &(buf.ptr[buf.position + buf.offset]), len);
|
|
buf.count = result;
|
|
|
|
if (result == -1)
|
|
{
|
|
if (errno == EAGAIN) /* Non-blocking */
|
|
result = 0;
|
|
else
|
|
{
|
|
JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
|
|
JCL_ThrowException(env, IO_EXCEPTION, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* Implementation of a scattering read. Will use the appropriate
|
|
* vector based read call (currently readv on Linux).
|
|
*
|
|
* This has a limit to the number of buffers that will be read. It
|
|
* will not make muliple readv calls. This is to ensure that operations
|
|
* are atomic. Currently it is limited to 16 buffers. This is for
|
|
* compatibiliy with Sun.
|
|
*/
|
|
JNIEXPORT jlong JNICALL
|
|
Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env,
|
|
jobject o __attribute__ ((__unused__)),
|
|
jint fd,
|
|
jobjectArray bbufs,
|
|
jint offset,
|
|
jint length)
|
|
{
|
|
jint i;
|
|
/* jboolean is_error = JNI_FALSE; */
|
|
/* char *error_msg; */
|
|
struct iovec buffers[JCL_IOV_MAX];
|
|
struct JCL_buffer bi_list[JCL_IOV_MAX];
|
|
ssize_t result;
|
|
jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
|
|
jlong bytes_read = 0;
|
|
|
|
/* Build the vector of buffers to read into */
|
|
for (i = 0; i < vec_len; i++)
|
|
{
|
|
struct JCL_buffer* buf;
|
|
jobject bbuf;
|
|
|
|
buf = &bi_list[i];
|
|
bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
|
|
|
|
JCL_init_buffer(env, buf, bbuf);
|
|
|
|
buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
|
|
buffers[i].iov_len = buf->limit - buf->position;
|
|
(*env)->DeleteLocalRef(env, bbuf);
|
|
}
|
|
|
|
/* Work the scattering magic */
|
|
result = readv(fd, buffers, vec_len);
|
|
bytes_read = (jlong) result;
|
|
|
|
/* Handle the response */
|
|
if (result < 0)
|
|
{
|
|
if (errno == EAGAIN) /* Non blocking */
|
|
result = 0;
|
|
else if (errno == EBADF) /* Bad fd */
|
|
{
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
|
|
JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
|
|
strerror(errno));
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
|
|
JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
|
|
return -1;
|
|
}
|
|
bytes_read = 0;
|
|
}
|
|
else if (result == 0) /* EOF */
|
|
{
|
|
result = -1;
|
|
}
|
|
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
|
|
|
|
return (jlong) result;
|
|
}
|
|
|
|
/*
|
|
* Implementation of a gathering write. Will use the appropriate
|
|
* vector based read call (currently readv on Linux).
|
|
*
|
|
* This has a limit to the number of buffers that will be read. It
|
|
* will not make muliple readv calls. This is to ensure that operations
|
|
* are atomic. Currently it is limited to 16 buffers. This is for
|
|
* compatibiliy with Sun.
|
|
*/
|
|
JNIEXPORT jlong JNICALL
|
|
Java_gnu_java_nio_VMChannel_writeGathering (JNIEnv *env,
|
|
jobject o __attribute__ ((__unused__)),
|
|
jint fd,
|
|
jobjectArray bbufs,
|
|
jint offset,
|
|
jint length)
|
|
{
|
|
int i;
|
|
/* jboolean is_error = JNI_FALSE; */
|
|
/* char *error_msg; */
|
|
struct iovec buffers[JCL_IOV_MAX];
|
|
struct JCL_buffer bi_list[JCL_IOV_MAX];
|
|
ssize_t result;
|
|
jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
|
|
jlong bytes_written;
|
|
|
|
|
|
/* Build the vector of buffers to read into */
|
|
for (i = 0; i < vec_len; i++)
|
|
{
|
|
struct JCL_buffer* buf;
|
|
jobject bbuf;
|
|
|
|
buf = &bi_list[i];
|
|
bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
|
|
|
|
JCL_init_buffer(env, buf, bbuf);
|
|
|
|
buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
|
|
buffers[i].iov_len = buf->limit - buf->position;
|
|
(*env)->DeleteLocalRef(env, bbuf);
|
|
}
|
|
|
|
/* Work the gathering magic */
|
|
result = writev(fd, buffers, vec_len);
|
|
bytes_written = (jlong) result;
|
|
|
|
if (result < 0)
|
|
{
|
|
bytes_written = 0;
|
|
if (errno == EAGAIN) /* Non blocking */
|
|
result = 0;
|
|
else if (errno == EBADF) /* Bad fd */
|
|
{
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
|
|
bytes_written);
|
|
JCL_ThrowException (env, NON_WRITABLE_CHANNEL_EXCEPTION,
|
|
strerror(errno));
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
|
|
bytes_written);
|
|
JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
else if (result == 0) /* EOF?? Does this happen on a write */
|
|
result = -1;
|
|
|
|
JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_written);
|
|
return (jlong) result;
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|