Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/JAVA/Openjdk/src/java.base/share/classes/sun/nio/ch/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 20 kB image not shown  

Quelle  IOUtil.java   Sprache: JAVA

 
/*
 * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package sun.nio.ch;

import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.MemorySessionImpl;

/**
 * File-descriptor based I/O utilities that are shared by NIO classes.
 */


public final class IOUtil {

    /**
     * Max number of iovec structures that readv/writev supports
     */

    static final int IOV_MAX;

    /**
     * Max total number of bytes that writev supports
     */

    static final long WRITEV_MAX;

    private IOUtil() { }                // No instantiation

    static int write(FileDescriptor fd, ByteBuffer src, long position,
                     NativeDispatcher nd)
        throws IOException
    {
        return write(fd, src, position, falsefalse, -1, nd);
    }

    static int write(FileDescriptor fd, ByteBuffer src, long position,
                     boolean async, NativeDispatcher nd)
        throws IOException
    {
        return write(fd, src, position, false, async, -1, nd);
    }

    static int write(FileDescriptor fd, ByteBuffer src, long position,
                     boolean directIO, int alignment, NativeDispatcher nd)
        throws IOException
    {
        return write(fd, src, position, directIO, false, alignment, nd);
    }

    static int write(FileDescriptor fd, ByteBuffer src, long position,
                     boolean directIO, boolean async, int alignment,
                     NativeDispatcher nd)
        throws IOException
    {
        if (src instanceof DirectBuffer) {
            return writeFromNativeBuffer(fd, src, position, directIO, async, alignment, nd);
        }

        // Substitute a native buffer
        int pos = src.position();
        int lim = src.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        ByteBuffer bb;
        if (directIO) {
            Util.checkRemainingBufferSizeAligned(rem, alignment);
            bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
        } else {
            bb = Util.getTemporaryDirectBuffer(rem);
        }
        try {
            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, directIO, async, alignment, nd);
            if (n > 0) {
                // now update src
                src.position(pos + n);
            }
            return n;
        } finally {
            Util.offerFirstTemporaryDirectBuffer(bb);
        }
    }

    private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
                                             long position, boolean directIO,
                                             boolean async, int alignment,
                                             NativeDispatcher nd)
        throws IOException
    {
        int pos = bb.position();
        int lim = bb.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);

        if (directIO) {
            Util.checkBufferPositionAligned(bb, pos, alignment);
            Util.checkRemainingBufferSizeAligned(rem, alignment);
        }

        int written = 0;
        if (rem == 0)
            return 0;
        acquireScope(bb, async);
        try {
            if (position != -1) {
                written = nd.pwrite(fd, bufferAddress(bb) + pos, rem, position);
            } else {
                written = nd.write(fd, bufferAddress(bb) + pos, rem);
            }
        } finally {
            releaseScope(bb);
        }
        if (written > 0)
            bb.position(pos + written);
        return written;
    }

    static long write(FileDescriptor fd, ByteBuffer[] bufs, boolean async,
                      NativeDispatcher nd)
        throws IOException
    {
        return write(fd, bufs, 0, bufs.length, false, async, -1, nd);
    }

    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                      NativeDispatcher nd)
        throws IOException
    {
        return write(fd, bufs, offset, length, falsefalse, -1, nd);
    }

    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                      boolean direct, int alignment, NativeDispatcher nd)
        throws IOException
    {
        return write(fd, bufs, offset, length, direct, false, alignment, nd);
    }

    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                      boolean directIO, boolean async,
                      int alignment, NativeDispatcher nd)
        throws IOException
    {
        IOVecWrapper vec = IOVecWrapper.get(length);

        boolean completed = false;
        int iov_len = 0;
        Runnable handleReleasers = null;
        try {
            // Iterate over buffers to populate native iovec array.
            long writevLen = 0L;
            int count = offset + length;
            int i = offset;
            while (i < count && iov_len < IOV_MAX && writevLen < WRITEV_MAX) {
                ByteBuffer buf = bufs[i];
                acquireScope(buf, async);
                if (NIO_ACCESS.hasSession(buf)) {
                    handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
                }
                int pos = buf.position();
                int lim = buf.limit();
                assert (pos <= lim);
                int rem = (pos <= lim ? lim - pos : 0);
                if (directIO)
                    Util.checkRemainingBufferSizeAligned(rem, alignment);

                if (rem > 0) {
                    long headroom = WRITEV_MAX - writevLen;
                    if (headroom < rem)
                        rem = (int)headroom;

                    vec.setBuffer(iov_len, buf, pos, rem);

                    // allocate shadow buffer to ensure I/O is done with direct buffer
                    if (!(buf instanceof DirectBuffer)) {
                        ByteBuffer shadow;
                        if (directIO)
                            shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
                        else
                            shadow = Util.getTemporaryDirectBuffer(rem);
                        shadow.put(shadow.position(), buf, pos, rem);
                        shadow.flip();
                        vec.setShadow(iov_len, shadow);
                        buf = shadow;
                        pos = shadow.position();
                    }

                    vec.putBase(iov_len, bufferAddress(buf) + pos);
                    vec.putLen(iov_len, rem);
                    iov_len++;
                    writevLen += rem;
                }
                i++;
            }
            if (iov_len == 0)
                return 0L;

            long bytesWritten = nd.writev(fd, vec.address, iov_len);

            // Notify the buffers how many bytes were taken
            long left = bytesWritten;
            for (int j=0; j<iov_len; j++) {
                if (left > 0) {
                    ByteBuffer buf = vec.getBuffer(j);
                    int pos = vec.getPosition(j);
                    int rem = vec.getRemaining(j);
                    int n = (left > rem) ? rem : (int)left;
                    buf.position(pos + n);
                    left -= n;
                }
                // return shadow buffers to buffer pool
                ByteBuffer shadow = vec.getShadow(j);
                if (shadow != null)
                    Util.offerLastTemporaryDirectBuffer(shadow);
                vec.clearRefs(j);
            }

            completed = true;
            return bytesWritten;

        } finally {
            releaseScopes(handleReleasers);
            // if an error occurred then clear refs to buffers and return any shadow
            // buffers to cache
            if (!completed) {
                for (int j=0; j<iov_len; j++) {
                    ByteBuffer shadow = vec.getShadow(j);
                    if (shadow != null)
                        Util.offerLastTemporaryDirectBuffer(shadow);
                    vec.clearRefs(j);
                }
            }
        }
    }

    static int read(FileDescriptor fd, ByteBuffer dst, long position,
                    NativeDispatcher nd)
        throws IOException
    {
        return read(fd, dst, position, falsefalse, -1, nd);
    }

    static int read(FileDescriptor fd, ByteBuffer dst, long position,
                    boolean async, NativeDispatcher nd)
        throws IOException
    {
        return read(fd, dst, position, false, async, -1, nd);
    }

    static int read(FileDescriptor fd, ByteBuffer dst, long position,
                    boolean directIO, int alignment, NativeDispatcher nd)
        throws IOException
    {
        return read(fd, dst, position, directIO, false, alignment, nd);
    }

    static int read(FileDescriptor fd, ByteBuffer dst, long position,
                    boolean directIO, boolean async,
                    int alignment, NativeDispatcher nd)
        throws IOException
    {
        if (dst.isReadOnly())
            throw new IllegalArgumentException("Read-only buffer");
        if (dst instanceof DirectBuffer)
            return readIntoNativeBuffer(fd, dst, position, directIO, async, alignment, nd);

        // Substitute a native buffer
        ByteBuffer bb;
        int rem = dst.remaining();
        if (directIO) {
            Util.checkRemainingBufferSizeAligned(rem, alignment);
            bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
        } else {
            bb = Util.getTemporaryDirectBuffer(rem);
        }
        try {
            int n = readIntoNativeBuffer(fd, bb, position, directIO, async, alignment, nd);
            bb.flip();
            if (n > 0)
                dst.put(bb);
            return n;
        } finally {
            Util.offerFirstTemporaryDirectBuffer(bb);
        }
    }

    private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
                                            long position, boolean directIO,
                                            boolean async, int alignment,
                                            NativeDispatcher nd)
        throws IOException
    {
        int pos = bb.position();
        int lim = bb.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);

        if (directIO) {
            Util.checkBufferPositionAligned(bb, pos, alignment);
            Util.checkRemainingBufferSizeAligned(rem, alignment);
        }

        if (rem == 0)
            return 0;
        int n = 0;
        acquireScope(bb, async);
        try {
            if (position != -1) {
                n = nd.pread(fd, bufferAddress(bb) + pos, rem, position);
            } else {
                n = nd.read(fd, bufferAddress(bb) + pos, rem);
            }
        } finally {
            releaseScope(bb);
        }
        if (n > 0)
            bb.position(pos + n);
        return n;
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
        throws IOException
    {
        return read(fd, bufs, 0, bufs.length, falsefalse, -1, nd);
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, boolean async,
                     NativeDispatcher nd)
        throws IOException
    {
        return read(fd, bufs, 0, bufs.length, false, async, -1, nd);
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                     NativeDispatcher nd)
        throws IOException
    {
        return read(fd, bufs, offset, length, falsefalse, -1, nd);
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                     boolean directIO, int alignment, NativeDispatcher nd)

        throws IOException
    {
        return read(fd, bufs, offset, length, directIO, false, alignment, nd);
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                     boolean directIO, boolean async,
                     int alignment, NativeDispatcher nd)

        throws IOException
    {
        IOVecWrapper vec = IOVecWrapper.get(length);

        boolean completed = false;
        int iov_len = 0;
        Runnable handleReleasers = null;
        try {
            // Iterate over buffers to populate native iovec array.
            int count = offset + length;
            int i = offset;
            while (i < count && iov_len < IOV_MAX) {
                ByteBuffer buf = bufs[i];
                if (buf.isReadOnly())
                    throw new IllegalArgumentException("Read-only buffer");
                acquireScope(buf, async);
                if (NIO_ACCESS.hasSession(buf)) {
                    handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
                }
                int pos = buf.position();
                int lim = buf.limit();
                assert (pos <= lim);
                int rem = (pos <= lim ? lim - pos : 0);

                if (directIO)
                    Util.checkRemainingBufferSizeAligned(rem, alignment);

                if (rem > 0) {
                    vec.setBuffer(iov_len, buf, pos, rem);

                    // allocate shadow buffer to ensure I/O is done with direct buffer
                    if (!(buf instanceof DirectBuffer)) {
                        ByteBuffer shadow;
                        if (directIO) {
                            shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
                        } else {
                            shadow = Util.getTemporaryDirectBuffer(rem);
                        }
                        vec.setShadow(iov_len, shadow);
                        buf = shadow;
                        pos = shadow.position();
                    }

                    vec.putBase(iov_len, bufferAddress(buf) + pos);
                    vec.putLen(iov_len, rem);
                    iov_len++;
                }
                i++;
            }
            if (iov_len == 0)
                return 0L;

            long bytesRead = nd.readv(fd, vec.address, iov_len);

            // Notify the buffers how many bytes were read
            long left = bytesRead;
            for (int j=0; j<iov_len; j++) {
                ByteBuffer shadow = vec.getShadow(j);
                if (left > 0) {
                    ByteBuffer buf = vec.getBuffer(j);
                    int rem = vec.getRemaining(j);
                    int n = (left > rem) ? rem : (int)left;
                    if (shadow == null) {
                        int pos = vec.getPosition(j);
                        buf.position(pos + n);
                    } else {
                        shadow.limit(shadow.position() + n);
                        buf.put(shadow);
                    }
                    left -= n;
                }
                if (shadow != null)
                    Util.offerLastTemporaryDirectBuffer(shadow);
                vec.clearRefs(j);
            }

            completed = true;
            return bytesRead;

        } finally {
            releaseScopes(handleReleasers);
            // if an error occurred then clear refs to buffers and return any shadow
            // buffers to cache
            if (!completed) {
                for (int j=0; j<iov_len; j++) {
                    ByteBuffer shadow = vec.getShadow(j);
                    if (shadow != null)
                        Util.offerLastTemporaryDirectBuffer(shadow);
                    vec.clearRefs(j);
                }
            }
        }
    }

    private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();

    static void acquireScope(ByteBuffer bb, boolean async) {
        if (async && NIO_ACCESS.isThreadConfined(bb)) {
            throw new IllegalStateException("Confined session not supported");
        }
        NIO_ACCESS.acquireSession(bb);
    }

    private static void releaseScope(ByteBuffer bb) {
        try {
            NIO_ACCESS.releaseSession(bb);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    static Runnable acquireScopes(ByteBuffer[] buffers) {
        return acquireScopes(null, buffers);
    }

    static Runnable acquireScopes(ByteBuffer buf, ByteBuffer[] buffers) {
        if (buffers == null) {
            assert buf != null;
            IOUtil.acquireScope(buf, true);
            return IOUtil.Releaser.of(buf);
        } else {
            assert buf == null;
            Runnable handleReleasers = null;
            for (var b : buffers) {
                IOUtil.acquireScope(b, true);
                handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(b), handleReleasers);
            }
            return handleReleasers;
        }
    }

    static void releaseScopes(Runnable releasers) {
        if (releasers != null)
            releasers.run();
    }

    record LinkedRunnable(Runnable node, Runnable next) implements Runnable {
        LinkedRunnable {
            Objects.requireNonNull(node);
        }

        @Override
        public void run() {
            try {
                node.run();
            } finally {
                if (next != null)
                    next.run();
            }
        }

        static LinkedRunnable of(Runnable first, Runnable second) {
            return new LinkedRunnable(first, second);
        }
    }

    record Releaser(ByteBuffer bb) implements Runnable {
        Releaser {
            Objects.requireNonNull(bb);
        }

        @Override
        public void run() {
            releaseScope(bb);
        }

        static Runnable of(ByteBuffer bb) {
            return NIO_ACCESS.hasSession(bb)
                    ? new Releaser(bb)
                    : () -> {};
        }

    }

    static long bufferAddress(ByteBuffer buf) {
        return NIO_ACCESS.getBufferAddress(buf);
    }

    public static FileDescriptor newFD(int i) {
        FileDescriptor fd = new FileDescriptor();
        setfdVal(fd, i);
        return fd;
    }

    static native boolean randomBytes(byte[] someBytes);

    /**
     * Returns two file descriptors for a pipe encoded in a long.
     * The read end of the pipe is returned in the high 32 bits,
     * while the write end is returned in the low 32 bits.
     */

    static native long makePipe(boolean blocking) throws IOException;

    static native int write1(int fd, byte b) throws IOException;

    /**
     * Read and discard all bytes.
     */

    static native boolean drain(int fd) throws IOException;

    /**
     * Read and discard at most one byte
     * @return the number of bytes read or IOS_INTERRUPTED
     */

    static native int drain1(int fd) throws IOException;

    public static native void configureBlocking(FileDescriptor fd,
                                                boolean blocking)
        throws IOException;

    public static native int fdVal(FileDescriptor fd);

    static native void setfdVal(FileDescriptor fd, int value);

    static native int fdLimit();

    static native int iovMax();

    static native long writevMax();

    static native void initIDs();

    /**
     * Used to trigger loading of native libraries
     */

    public static void load() { }

    static {
        jdk.internal.loader.BootLoader.loadLibrary("net");
        jdk.internal.loader.BootLoader.loadLibrary("nio");
        initIDs();

        IOV_MAX = iovMax();
        WRITEV_MAX = writevMax();
    }

}

Messung V0.5
C=96 H=89 G=92

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.