1136 lines · 37.4 KB · Java
RawDownload
        try {            Util.erase(bb);            while (tw < icount) {                bb.limit(Math.min((int)(icount - tw), TRANSFER_SIZE));                int nr = read(bb, pos);                if (nr <= 0)                    break;                bb.flip();                // ## Bug: Will block writing target if this channel                // ##      is asynchronously closed                int nw = target.write(bb);                tw += nw;                if (nw != nr)                    break;                pos += nw;                bb.clear();            }            return tw;        } catch (IOException x) {            if (tw > 0)                return tw;            throw x;        } finally {            Util.releaseTemporaryDirectBuffer(bb);        }    }     public long transferTo(long position, long count,                           WritableByteChannel target)        throws IOException    {        ensureOpen();        if (!target.isOpen())            throw new ClosedChannelException();        if (!readable)            throw new NonReadableChannelException();        if (target instanceof FileChannelImpl &&            !((FileChannelImpl)target).writable)            throw new NonWritableChannelException();        if ((position < 0) || (count < 0))            throw new IllegalArgumentException();        long sz = size();        if (position > sz)            return 0;        int icount = (int)Math.min(count, Integer.MAX_VALUE);        if ((sz - position) < icount)            icount = (int)(sz - position);         long n;         // Attempt a direct transfer, if the kernel supports it        if ((n = transferToDirectly(position, icount, target)) >= 0)            return n;         // Attempt a mapped transfer, but only to trusted channel types        if ((n = transferToTrustedChannel(position, icount, target)) >= 0)            return n;         // Slow path for untrusted targets        return transferToArbitraryChannel(position, icount, target);    }     private long transferFromFileChannel(FileChannelImpl src,                                         long position, long count)        throws IOException    {        if (!src.readable)            throw new NonReadableChannelException();        synchronized (src.positionLock) {            long pos = src.position();            long max = Math.min(count, src.size() - pos);             long remaining = max;            long p = pos;            while (remaining > 0L) {                long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);                // ## Bug: Closing this channel will not terminate the write                MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);                try {                    long n = write(bb, position);                    assert n > 0;                    p += n;                    position += n;                    remaining -= n;                } catch (IOException ioe) {                    // Only throw exception if no bytes have been written                    if (remaining == max)                        throw ioe;                    break;                } finally {                    unmap(bb);                }            }            long nwritten = max - remaining;            src.position(pos + nwritten);            return nwritten;        }    }     private static final int TRANSFER_SIZE = 8192;     private long transferFromArbitraryChannel(ReadableByteChannel src,                                              long position, long count)        throws IOException    {        // Untrusted target: Use a newly-erased buffer        int c = (int)Math.min(count, TRANSFER_SIZE);        ByteBuffer bb = Util.getTemporaryDirectBuffer(c);        long tw = 0;                    // Total bytes written        long pos = position;        try {            Util.erase(bb);            while (tw < count) {                bb.limit((int)Math.min((count - tw), (long)TRANSFER_SIZE));                // ## Bug: Will block reading src if this channel                // ##      is asynchronously closed                int nr = src.read(bb);                if (nr <= 0)                    break;                bb.flip();                int nw = write(bb, pos);                tw += nw;                if (nw != nr)                    break;                pos += nw;                bb.clear();            }            return tw;        } catch (IOException x) {            if (tw > 0)                return tw;            throw x;        } finally {            Util.releaseTemporaryDirectBuffer(bb);        }    }     public long transferFrom(ReadableByteChannel src,                             long position, long count)        throws IOException    {        ensureOpen();        if (!src.isOpen())            throw new ClosedChannelException();        if (!writable)            throw new NonWritableChannelException();        if ((position < 0) || (count < 0))            throw new IllegalArgumentException();        if (position > size())            return 0;        if (src instanceof FileChannelImpl)           return transferFromFileChannel((FileChannelImpl)src,                                          position, count);         return transferFromArbitraryChannel(src, position, count);    }     public int read(ByteBuffer dst, long position) throws IOException {        if (dst == null)            throw new NullPointerException();        if (position < 0)            throw new IllegalArgumentException("Negative position");        if (!readable)            throw new NonReadableChannelException();        ensureOpen();        int n = 0;        int ti = -1;        try {            begin();            ti = threads.add();            if (!isOpen())                return -1;            do {                n = IOUtil.read(fd, dst, position, nd, positionLock);            } while ((n == IOStatus.INTERRUPTED) && isOpen());            return IOStatus.normalize(n);        } finally {            threads.remove(ti);            end(n > 0);            assert IOStatus.check(n);        }    }     public int write(ByteBuffer src, long position) throws IOException {        if (src == null)            throw new NullPointerException();        if (position < 0)            throw new IllegalArgumentException("Negative position");        if (!writable)            throw new NonWritableChannelException();        ensureOpen();        int n = 0;        int ti = -1;        try {            begin();            ti = threads.add();            if (!isOpen())                return -1;            do {                n = IOUtil.write(fd, src, position, nd, positionLock);            } while ((n == IOStatus.INTERRUPTED) && isOpen());            return IOStatus.normalize(n);        } finally {            threads.remove(ti);            end(n > 0);            assert IOStatus.check(n);        }    }      // -- Memory-mapped buffers --     private static class Unmapper        implements Runnable    {        // may be required to close file        private static final NativeDispatcher nd = new FileDispatcherImpl();         // keep track of mapped buffer usage        static volatile int count;        static volatile long totalSize;        static volatile long totalCapacity;         private volatile long address;        private final long size;        private final int cap;        private final FileDescriptor fd;         private Unmapper(long address, long size, int cap,                         FileDescriptor fd)        {            assert (address != 0);            this.address = address;            this.size = size;            this.cap = cap;            this.fd = fd;             synchronized (Unmapper.class) {                count++;                totalSize += size;                totalCapacity += cap;            }        }         public void run() {            if (address == 0)                return;            unmap0(address, size);            address = 0;             // if this mapping has a valid file descriptor then we close it            if (fd.valid()) {                try {                    nd.close(fd);                } catch (IOException ignore) {                    // nothing we can do                }            }             synchronized (Unmapper.class) {                count--;                totalSize -= size;                totalCapacity -= cap;            }        }    }     private static void unmap(MappedByteBuffer bb) {        Cleaner cl = ((DirectBuffer)bb).cleaner();        if (cl != null)            cl.clean();    }     private static final int MAP_RO = 0;    private static final int MAP_RW = 1;    private static final int MAP_PV = 2;     public MappedByteBuffer map(MapMode mode, long position, long size)        throws IOException    {        ensureOpen();        if (position < 0L)            throw new IllegalArgumentException("Negative position");        if (size < 0L)            throw new IllegalArgumentException("Negative size");        if (position + size < 0)            throw new IllegalArgumentException("Position + size overflow");        if (size > Integer.MAX_VALUE)            throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");        int imode = -1;        if (mode == MapMode.READ_ONLY)            imode = MAP_RO;        else if (mode == MapMode.READ_WRITE)            imode = MAP_RW;        else if (mode == MapMode.PRIVATE)            imode = MAP_PV;        assert (imode >= 0);        if ((mode != MapMode.READ_ONLY) && !writable)            throw new NonWritableChannelException();        if (!readable)            throw new NonReadableChannelException();         long addr = -1;        int ti = -1;        try {            begin();            ti = threads.add();            if (!isOpen())                return null;            if (size() < position + size) { // Extend file size                if (!writable) {                    throw new IOException("Channel not open for writing " +                        "- cannot extend file to required size");                }                int rv;                do {                    rv = nd.truncate(fd, position + size);                } while ((rv == IOStatus.INTERRUPTED) && isOpen());            }            if (size == 0) {                addr = 0;                // a valid file descriptor is not required                FileDescriptor dummy = new FileDescriptor();                if ((!writable) || (imode == MAP_RO))                    return Util.newMappedByteBufferR(0, 0, dummy, null);                else                    return Util.newMappedByteBuffer(0, 0, dummy, null);            }             int pagePosition = (int)(position % allocationGranularity);            long mapPosition = position - pagePosition;            long mapSize = size + pagePosition;            try {                // If no exception was thrown from map0, the address is valid                addr = map0(imode, mapPosition, mapSize);            } catch (OutOfMemoryError x) {                // An OutOfMemoryError may indicate that we've exhausted memory                // so force gc and re-attempt map                System.gc();                try {                    Thread.sleep(100);                } catch (InterruptedException y) {                    Thread.currentThread().interrupt();                }                try {                    addr = map0(imode, mapPosition, mapSize);                } catch (OutOfMemoryError y) {                    // After a second OOME, fail                    throw new IOException("Map failed", y);                }            }             // On Windows, and potentially other platforms, we need an open            // file descriptor for some mapping operations.            FileDescriptor mfd;            try {                mfd = nd.duplicateForMapping(fd);            } catch (IOException ioe) {                unmap0(addr, mapSize);                throw ioe;            }             assert (IOStatus.checkAll(addr));            assert (addr % allocationGranularity == 0);            int isize = (int)size;            Unmapper um = new Unmapper(addr, mapSize, isize, mfd);            if ((!writable) || (imode == MAP_RO)) {                return Util.newMappedByteBufferR(isize,                                                 addr + pagePosition,                                                 mfd,                                                 um);            } else {                return Util.newMappedByteBuffer(isize,                                                addr + pagePosition,                                                mfd,                                                um);            }        } finally {            threads.remove(ti);            end(IOStatus.checkAll(addr));        }    }     /**     * Invoked by sun.management.ManagementFactoryHelper to create the management     * interface for mapped buffers.     */    public static sun.misc.JavaNioAccess.BufferPool getMappedBufferPool() {        return new sun.misc.JavaNioAccess.BufferPool() {            @Override            public String getName() {                return "mapped";            }            @Override            public long getCount() {                return Unmapper.count;            }            @Override            public long getTotalCapacity() {                return Unmapper.totalCapacity;            }            @Override            public long getMemoryUsed() {                return Unmapper.totalSize;            }        };    }     // -- Locks --       // keeps track of locks on this file    private volatile FileLockTable fileLockTable;     // indicates if file locks are maintained system-wide (as per spec)    private static boolean isSharedFileLockTable;     // indicates if the disableSystemWideOverlappingFileLockCheck property    // has been checked    private static volatile boolean propertyChecked;     // The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so    // the overlap check wasn't system wide when there were multiple channels to    // the same file. This property is used to get 1.4/5.0 behavior if desired.    private static boolean isSharedFileLockTable() {        if (!propertyChecked) {            synchronized (FileChannelImpl.class) {                if (!propertyChecked) {                    String value = AccessController.doPrivileged(                        new GetPropertyAction(                            "sun.nio.ch.disableSystemWideOverlappingFileLockCheck"));                    isSharedFileLockTable = ((value == null) || value.equals("false"));                    propertyChecked = true;                }            }        }        return isSharedFileLockTable;    }     private FileLockTable fileLockTable() throws IOException {        if (fileLockTable == null) {            synchronized (this) {                if (fileLockTable == null) {                    if (isSharedFileLockTable()) {                        int ti = threads.add();                        try {                            ensureOpen();                            fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);                        } finally {                            threads.remove(ti);                        }                    } else {                        fileLockTable = new SimpleFileLockTable();                    }                }            }        }        return fileLockTable;    }     public FileLock lock(long position, long size, boolean shared)        throws IOException    {        ensureOpen();        if (shared && !readable)            throw new NonReadableChannelException();        if (!shared && !writable)            throw new NonWritableChannelException();        FileLockImpl fli = new FileLockImpl(this, position, size, shared);        FileLockTable flt = fileLockTable();        flt.add(fli);        boolean completed = false;        int ti = -1;        try {            begin();            ti = threads.add();            if (!isOpen())                return null;            int n;            do {                n = nd.lock(fd, true, position, size, shared);            } while ((n == FileDispatcher.INTERRUPTED) && isOpen());            if (isOpen()) {                if (n == FileDispatcher.RET_EX_LOCK) {                    assert shared;                    FileLockImpl fli2 = new FileLockImpl(this, position, size,                                                         false);                    flt.replace(fli, fli2);                    fli = fli2;                }                completed = true;            }        } finally {            if (!completed)                flt.remove(fli);            threads.remove(ti);            try {                end(completed);            } catch (ClosedByInterruptException e) {

Lines 501–1000 of 1136. Previous lines