File-descriptor based I/O utilities that are shared by NIO classes.
| Method from sun.nio.ch.IOUtil Detail: |
static native void configureBlocking(FileDescriptor fd,
boolean blocking) throws IOException
|
static native boolean drain(int fd) throws IOException
|
static native int fdVal(FileDescriptor fd)
|
static native void initIDs()
|
static native void initPipe(int[] fda,
boolean blocking)
|
static FileDescriptor newFD(int i) {
FileDescriptor fd = new FileDescriptor();
setfdVal(fd, i);
return fd;
}
|
static native boolean randomBytes(byte[] someBytes)
|
static long read(FileDescriptor fd,
ByteBuffer[] bufs,
NativeDispatcher nd) throws IOException {
int nextWithRemaining = remaining(bufs);
// if all bufs are empty we should return immediately
if (nextWithRemaining < 0)
return 0;
// If some bufs are empty we should skip them
if (nextWithRemaining > 0)
bufs = skipBufs(bufs, nextWithRemaining);
int numBufs = bufs.length;
// Read into the shadow to ensure DirectByteBuffers are used
ByteBuffer[] shadow = new ByteBuffer[numBufs];
for (int i=0; i< numBufs; i++) {
if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (!(bufs[i] instanceof DirectBuffer)) {
shadow[i] = ByteBuffer.allocateDirect(bufs[i].remaining());
} else {
shadow[i] = bufs[i];
}
}
IOVecWrapper vec = null;
long bytesRead = 0;
try {
// Create a native iovec array
vec = new IOVecWrapper(numBufs);
// Fill in the iovec array with appropriate data
for (int i=0; i< numBufs; i++) {
ByteBuffer nextBuffer = shadow[i];
// put in the buffer addresses
long pos = nextBuffer.position();
long len = nextBuffer.remaining();
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
vec.putLen(i, len);
}
// Invoke native call to fill the buffers
bytesRead = nd.readv(fd, vec.address, numBufs);
} finally {
vec.free();
}
long returnVal = bytesRead;
// Notify the buffers how many bytes were read
for (int i=0; i< numBufs; i++) {
ByteBuffer nextBuffer = shadow[i];
// Note: should this have been cached from above?
int pos = nextBuffer.position();
int len = nextBuffer.remaining();
if (bytesRead >= len) {
bytesRead -= len;
int newPosition = pos + len;
nextBuffer.position(newPosition);
} else { // Buffers not completely filled
if (bytesRead > 0) {
assert(pos + bytesRead < (long)Integer.MAX_VALUE);
int newPosition = (int)(pos + bytesRead);
nextBuffer.position(newPosition);
}
break;
}
}
// Put results from shadow into the slow buffers
for (int i=0; i< numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
shadow[i].flip();
bufs[i].put(shadow[i]);
}
}
return returnVal;
}
|
static int read(FileDescriptor fd,
ByteBuffer dst,
long position,
NativeDispatcher nd,
Object lock) throws IOException {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (dst instanceof DirectBuffer)
return readIntoNativeBuffer(fd, dst, position, nd, lock);
// Substitute a native buffer
ByteBuffer bb = null;
try {
bb = Util.getTemporaryDirectBuffer(dst.remaining());
int n = readIntoNativeBuffer(fd, bb, position, nd, lock);
bb.flip();
if (n > 0)
dst.put(bb);
return n;
} finally {
Util.releaseTemporaryDirectBuffer(bb);
}
}
|
static native void setfdVal(FileDescriptor fd,
int value)
|
static long write(FileDescriptor fd,
ByteBuffer[] bufs,
NativeDispatcher nd) throws IOException {
int nextWithRemaining = remaining(bufs);
// if all bufs are empty we should return immediately
if (nextWithRemaining < 0)
return 0;
// If some bufs are empty we should skip them
if (nextWithRemaining > 0)
bufs = skipBufs(bufs, nextWithRemaining);
int numBufs = bufs.length;
int bytesReadyToWrite = 0;
// Create shadow to ensure DirectByteBuffers are used
ByteBuffer[] shadow = new ByteBuffer[numBufs];
for (int i=0; i< numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
int pos = bufs[i].position();
int lim = bufs[i].limit();
assert (pos < = lim);
int rem = (pos < = lim ? lim - pos : 0);
ByteBuffer bb = ByteBuffer.allocateDirect(rem);
shadow[i] = bb;
// Leave slow buffer position untouched; it will be updated
// after we see how many bytes were really written out
bb.put(bufs[i]);
bufs[i].position(pos);
bb.flip();
} else {
shadow[i] = bufs[i];
}
}
IOVecWrapper vec = null;
long bytesWritten = 0;
try {
// Create a native iovec array
vec= new IOVecWrapper(numBufs);
// Fill in the iovec array with appropriate data
for (int i=0; i< numBufs; i++) {
ByteBuffer nextBuffer = shadow[i];
// put in the buffer addresses
long pos = nextBuffer.position();
long len = nextBuffer.limit() - pos;
bytesReadyToWrite += len;
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
vec.putLen(i, len);
}
// Invoke native call to fill the buffers
bytesWritten = nd.writev(fd, vec.address, numBufs);
} finally {
vec.free();
}
long returnVal = bytesWritten;
// Notify the buffers how many bytes were taken
for (int i=0; i< numBufs; i++) {
ByteBuffer nextBuffer = bufs[i];
int pos = nextBuffer.position();
int lim = nextBuffer.limit();
assert (pos < = lim);
int len = (pos < = lim ? lim - pos : lim);
if (bytesWritten >= len) {
bytesWritten -= len;
int newPosition = pos + len;
nextBuffer.position(newPosition);
} else { // Buffers not completely filled
if (bytesWritten > 0) {
assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
int newPosition = (int)(pos + bytesWritten);
nextBuffer.position(newPosition);
}
break;
}
}
return returnVal;
}
|
static int write(FileDescriptor fd,
ByteBuffer src,
long position,
NativeDispatcher nd,
Object lock) throws IOException {
if (src instanceof DirectBuffer)
return writeFromNativeBuffer(fd, src, position, nd, lock);
// Substitute a native buffer
int pos = src.position();
int lim = src.limit();
assert (pos < = lim);
int rem = (pos < = lim ? lim - pos : 0);
ByteBuffer bb = null;
try {
bb = Util.getTemporaryDirectBuffer(rem);
bb.put(src);
bb.flip();
// Do not update src until we see how many bytes were written
src.position(pos);
int n = writeFromNativeBuffer(fd, bb, position, nd, lock);
if (n > 0) {
// now update src
src.position(pos + n);
}
return n;
} finally {
Util.releaseTemporaryDirectBuffer(bb);
}
}
|