|
Java example source code file (netty_unix_filedescriptor.c)
The netty_unix_filedescriptor.c Java example source code
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/uio.h>
#include "netty_unix_util.h"
#include "netty_unix_errors.h"
#include "netty_unix_filedescriptor.h"
static jmethodID posId = NULL;
static jmethodID limitId = NULL;
static jfieldID posFieldId = NULL;
static jfieldID limitFieldId = NULL;
// Optional external methods
extern int pipe2(int pipefd[2], int flags) __attribute__((weak));
static jint _write(JNIEnv* env, jclass clazz, jint fd, void* buffer, jint pos, jint limit) {
ssize_t res;
int err;
do {
res = write(fd, buffer + pos, (size_t) (limit - pos));
// keep on writing if it was interrupted
} while (res == -1 && ((err = errno) == EINTR));
if (res < 0) {
return -err;
}
return (jint) res;
}
static jlong _writev(JNIEnv* env, jclass clazz, jint fd, struct iovec* iov, jint length) {
ssize_t res;
int err;
do {
res = writev(fd, iov, length);
// keep on writing if it was interrupted
} while (res == -1 && ((err = errno) == EINTR));
if (res < 0) {
return -err;
}
return (jlong) res;
}
static jint _read(JNIEnv* env, jclass clazz, jint fd, void* buffer, jint pos, jint limit) {
ssize_t res;
int err;
do {
res = read(fd, buffer + pos, (size_t) (limit - pos));
// Keep on reading if we was interrupted
} while (res == -1 && ((err = errno) == EINTR));
if (res < 0) {
return -err;
}
return (jint) res;
}
// JNI Registered Methods Begin
static jint netty_unix_filedescriptor_close(JNIEnv* env, jclass clazz, jint fd) {
if (close(fd) < 0) {
return -errno;
}
return 0;
}
static jint netty_unix_filedescriptor_open(JNIEnv* env, jclass clazz, jstring path) {
const char* f_path = (*env)->GetStringUTFChars(env, path, 0);
int res = open(f_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
(*env)->ReleaseStringUTFChars(env, path, f_path);
if (res < 0) {
return -errno;
}
return res;
}
static jint netty_unix_filedescriptor_write(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit) {
// We check that GetDirectBufferAddress will not return NULL in OnLoad
return _write(env, clazz, fd, (*env)->GetDirectBufferAddress(env, jbuffer), pos, limit);
}
static jint netty_unix_filedescriptor_writeAddress(JNIEnv* env, jclass clazz, jint fd, jlong address, jint pos, jint limit) {
return _write(env, clazz, fd, (void*) (intptr_t) address, pos, limit);
}
static jlong netty_unix_filedescriptor_writevAddresses(JNIEnv* env, jclass clazz, jint fd, jlong memoryAddress, jint length) {
struct iovec* iov = (struct iovec*) (intptr_t) memoryAddress;
return _writev(env, clazz, fd, iov, length);
}
static jlong netty_unix_filedescriptor_writev(JNIEnv* env, jclass clazz, jint fd, jobjectArray buffers, jint offset, jint length) {
struct iovec iov[length];
int iovidx = 0;
int i;
int num = offset + length;
for (i = offset; i < num; i++) {
jobject bufObj = (*env)->GetObjectArrayElement(env, buffers, i);
jint pos;
// Get the current position using the (*env)->GetIntField if possible and fallback
// to slower (*env)->CallIntMethod(...) if needed
if (posFieldId == NULL) {
pos = (*env)->CallIntMethod(env, bufObj, posId, NULL);
} else {
pos = (*env)->GetIntField(env, bufObj, posFieldId);
}
jint limit;
// Get the current limit using the (*env)->GetIntField if possible and fallback
// to slower (*env)->CallIntMethod(...) if needed
if (limitFieldId == NULL) {
limit = (*env)->CallIntMethod(env, bufObj, limitId, NULL);
} else {
limit = (*env)->GetIntField(env, bufObj, limitFieldId);
}
void* buffer = (*env)->GetDirectBufferAddress(env, bufObj);
// We check that GetDirectBufferAddress will not return NULL in OnLoad
iov[iovidx].iov_base = buffer + pos;
iov[iovidx].iov_len = (size_t) (limit - pos);
iovidx++;
// Explicit delete local reference as otherwise the local references will only be released once the native method returns.
// Also there may be a lot of these and JNI specification only specify that 16 must be able to be created.
//
// See https://github.com/netty/netty/issues/2623
(*env)->DeleteLocalRef(env, bufObj);
}
return _writev(env, clazz, fd, iov, length);
}
static jint netty_unix_filedescriptor_read(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit) {
// We check that GetDirectBufferAddress will not return NULL in OnLoad
return _read(env, clazz, fd, (*env)->GetDirectBufferAddress(env, jbuffer), pos, limit);
}
static jint netty_unix_filedescriptor_readAddress(JNIEnv* env, jclass clazz, jint fd, jlong address, jint pos, jint limit) {
return _read(env, clazz, fd, (void*) (intptr_t) address, pos, limit);
}
static jlong netty_unix_filedescriptor_newPipe(JNIEnv* env, jclass clazz) {
int fd[2];
if (pipe2) {
// we can just use pipe2 and so save extra syscalls;
if (pipe2(fd, O_NONBLOCK) != 0) {
return -errno;
}
} else {
if (pipe(fd) == 0) {
if (fcntl(fd[0], F_SETFD, O_NONBLOCK) < 0) {
int err = errno;
close(fd[0]);
close(fd[1]);
return -err;
}
if (fcntl(fd[1], F_SETFD, O_NONBLOCK) < 0) {
int err = errno;
close(fd[0]);
close(fd[1]);
return -err;
}
} else {
return -errno;
}
}
// encode the fds into a 64 bit value
return (((jlong) fd[0]) << 32) | fd[1];
}
// JNI Registered Methods End
// JNI Method Registration Table Begin
static const JNINativeMethod method_table[] = {
{ "close", "(I)I", (void *) netty_unix_filedescriptor_close },
{ "open", "(Ljava/lang/String;)I", (void *) netty_unix_filedescriptor_open },
{ "write", "(ILjava/nio/ByteBuffer;II)I", (void *) netty_unix_filedescriptor_write },
{ "writeAddress", "(IJII)I", (void *) netty_unix_filedescriptor_writeAddress },
{ "writevAddresses", "(IJI)J", (void *) netty_unix_filedescriptor_writevAddresses },
{ "writev", "(I[Ljava/nio/ByteBuffer;II)J", (void *) netty_unix_filedescriptor_writev },
{ "read", "(ILjava/nio/ByteBuffer;II)I", (void *) netty_unix_filedescriptor_read },
{ "readAddress", "(IJII)I", (void *) netty_unix_filedescriptor_readAddress },
{ "newPipe", "()J", (void *) netty_unix_filedescriptor_newPipe }
};
static const jint method_table_size = sizeof(method_table) / sizeof(method_table[0]);
// JNI Method Registration Table End
jint netty_unix_filedescriptor_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
if (netty_unix_util_register_natives(env, packagePrefix, "io/netty/channel/unix/FileDescriptor", method_table, method_table_size) != 0) {
return JNI_ERR;
}
void* mem = malloc(1);
if (mem == NULL) {
netty_unix_errors_throwOutOfMemoryError(env);
return JNI_ERR;
}
jobject directBuffer = (*env)->NewDirectByteBuffer(env, mem, 1);
if (directBuffer == NULL) {
free(mem);
netty_unix_errors_throwOutOfMemoryError(env);
return JNI_ERR;
}
if ((*env)->GetDirectBufferAddress(env, directBuffer) == NULL) {
free(mem);
netty_unix_errors_throwRuntimeException(env, "failed to get direct buffer address");
return JNI_ERR;
}
jclass cls = (*env)->GetObjectClass(env, directBuffer);
// Get the method id for Buffer.position() and Buffer.limit(). These are used as fallback if
// it is not possible to obtain the position and limit using the fields directly.
posId = (*env)->GetMethodID(env, cls, "position", "()I");
if (posId == NULL) {
free(mem);
// position method was not found.. something is wrong so bail out
netty_unix_errors_throwRuntimeException(env, "failed to get method ID: ByteBuffer.position()");
return JNI_ERR;
}
limitId = (*env)->GetMethodID(env, cls, "limit", "()I");
if (limitId == NULL) {
free(mem);
// limit method was not found.. something is wrong so bail out
netty_unix_errors_throwRuntimeException(env, "failed to get method ID: ByteBuffer.limit()");
return JNI_ERR;
}
// Try to get the ids of the position and limit fields. We later then check if we was able
// to find them and if so use them get the position and limit of the buffer. This is
// much faster then call back into java via (*env)->CallIntMethod(...).
posFieldId = (*env)->GetFieldID(env, cls, "position", "I");
if (posFieldId == NULL) {
// this is ok as we can still use the method so just clear the exception
(*env)->ExceptionClear(env);
}
limitFieldId = (*env)->GetFieldID(env, cls, "limit", "I");
if (limitFieldId == NULL) {
// this is ok as we can still use the method so just clear the exception
(*env)->ExceptionClear(env);
}
free(mem);
return JNI_VERSION_1_6;
}
void netty_unix_filedescriptor_JNI_OnUnLoad(JNIEnv* env) { }
Other Java examples (source code examples)Here is a short list of links related to this Java netty_unix_filedescriptor.c source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.