< prev index next >

src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

Print this page

  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.lang.ref.Cleaner.Cleanable;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.nio.channels.AsynchronousCloseException;
  35 import java.nio.channels.ClosedByInterruptException;
  36 import java.nio.channels.ClosedChannelException;
  37 import java.nio.channels.FileChannel;
  38 import java.nio.channels.FileLock;
  39 import java.nio.channels.FileLockInterruptionException;
  40 import java.nio.channels.NonReadableChannelException;
  41 import java.nio.channels.NonWritableChannelException;
  42 import java.nio.channels.ReadableByteChannel;
  43 import java.nio.channels.SelectableChannel;
  44 import java.nio.channels.WritableByteChannel;
  45 import java.util.Objects;
  46 
  47 import jdk.internal.access.JavaIOFileDescriptorAccess;
  48 import jdk.internal.access.SharedSecrets;

  49 import jdk.internal.misc.ExtendedMapMode;
  50 import jdk.internal.misc.Unsafe;
  51 import jdk.internal.misc.VM;
  52 import jdk.internal.misc.VM.BufferPool;
  53 import jdk.internal.ref.Cleaner;
  54 import jdk.internal.ref.CleanerFactory;
  55 
  56 import jdk.internal.access.foreign.UnmapperProxy;
  57 
  58 public class FileChannelImpl
  59     extends FileChannel
  60 {
  61     // Memory allocation size for mapping buffers
  62     private static final long allocationGranularity;
  63 
  64     // Access to FileDescriptor internals
  65     private static final JavaIOFileDescriptorAccess fdAccess =
  66         SharedSecrets.getJavaIOFileDescriptorAccess();
  67 
  68     // Maximum direct transfer size

 212             fdAccess.close(fd);
 213         }
 214 
 215     }
 216 
 217     public int read(ByteBuffer dst) throws IOException {
 218         ensureOpen();
 219         if (!readable)
 220             throw new NonReadableChannelException();
 221         synchronized (positionLock) {
 222             if (direct)
 223                 Util.checkChannelPositionAligned(position(), alignment);
 224             int n = 0;
 225             int ti = -1;
 226             try {
 227                 beginBlocking();
 228                 ti = threads.add();
 229                 if (!isOpen())
 230                     return 0;
 231                 do {
 232                     n = IOUtil.read(fd, dst, -1, direct, alignment, nd);





 233                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 234                 return IOStatus.normalize(n);
 235             } finally {
 236                 threads.remove(ti);
 237                 endBlocking(n > 0);
 238                 assert IOStatus.check(n);
 239             }
 240         }
 241     }
 242 
 243     public long read(ByteBuffer[] dsts, int offset, int length)
 244         throws IOException
 245     {
 246         Objects.checkFromIndexSize(offset, length, dsts.length);
 247         ensureOpen();
 248         if (!readable)
 249             throw new NonReadableChannelException();
 250         synchronized (positionLock) {
 251             if (direct)
 252                 Util.checkChannelPositionAligned(position(), alignment);
 253             long n = 0;
 254             int ti = -1;
 255             try {
 256                 beginBlocking();
 257                 ti = threads.add();
 258                 if (!isOpen())
 259                     return 0;
 260                 do {
 261                     n = IOUtil.read(fd, dsts, offset, length,
 262                             direct, alignment, nd);




 263                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 264                 return IOStatus.normalize(n);
 265             } finally {
 266                 threads.remove(ti);
 267                 endBlocking(n > 0);
 268                 assert IOStatus.check(n);
 269             }
 270         }
 271     }
 272 
 273     public int write(ByteBuffer src) throws IOException {
 274         ensureOpen();
 275         if (!writable)
 276             throw new NonWritableChannelException();
 277         synchronized (positionLock) {
 278             if (direct)
 279                 Util.checkChannelPositionAligned(position(), alignment);
 280             int n = 0;
 281             int ti = -1;
 282             try {
 283                 beginBlocking();
 284                 ti = threads.add();
 285                 if (!isOpen())
 286                     return 0;
 287                 do {
 288                     n = IOUtil.write(fd, src, -1, direct, alignment, nd);





 289                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 290                 return IOStatus.normalize(n);
 291             } finally {
 292                 threads.remove(ti);
 293                 endBlocking(n > 0);
 294                 assert IOStatus.check(n);
 295             }
 296         }
 297     }
 298 
 299     public long write(ByteBuffer[] srcs, int offset, int length)
 300         throws IOException
 301     {
 302         Objects.checkFromIndexSize(offset, length, srcs.length);
 303         ensureOpen();
 304         if (!writable)
 305             throw new NonWritableChannelException();
 306         synchronized (positionLock) {
 307             if (direct)
 308                 Util.checkChannelPositionAligned(position(), alignment);
 309             long n = 0;
 310             int ti = -1;
 311             try {
 312                 beginBlocking();
 313                 ti = threads.add();
 314                 if (!isOpen())
 315                     return 0;
 316                 do {
 317                     n = IOUtil.write(fd, srcs, offset, length,
 318                             direct, alignment, nd);




 319                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 320                 return IOStatus.normalize(n);
 321             } finally {
 322                 threads.remove(ti);
 323                 endBlocking(n > 0);
 324                 assert IOStatus.check(n);
 325             }
 326         }
 327     }
 328 
 329     // -- Other operations --
 330 



























 331     public long position() throws IOException {
 332         ensureOpen();
 333         synchronized (positionLock) {
 334             long p = -1;
 335             int ti = -1;
 336             try {
 337                 beginBlocking();
 338                 ti = threads.add();
 339                 if (!isOpen())
 340                     return 0;
 341                 boolean append = fdAccess.getAppend(fd);
 342                 do {
 343                     // in append-mode then position is advanced to end before writing
 344                     p = (append) ? nd.size(fd) : nd.seek(fd, -1);
 345                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 346                 return IOStatus.normalize(p);
 347             } finally {
 348                 threads.remove(ti);
 349                 endBlocking(p > -1);
 350                 assert IOStatus.check(p);
 351             }
 352         }
 353     }
 354 
 355     public FileChannel position(long newPosition) throws IOException {
 356         ensureOpen();
 357         if (newPosition < 0)
 358             throw new IllegalArgumentException();
 359         synchronized (positionLock) {
 360             long p = -1;
 361             int ti = -1;
 362             try {
 363                 beginBlocking();
 364                 ti = threads.add();
 365                 if (!isOpen())
 366                     return null;
 367                 do {
 368                     p = nd.seek(fd, newPosition);
 369                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 370                 return this;
 371             } finally {
 372                 threads.remove(ti);
 373                 endBlocking(p > -1);
 374                 assert IOStatus.check(p);
 375             }
 376         }
 377     }
 378 
 379     public long size() throws IOException {
 380         ensureOpen();
 381         synchronized (positionLock) {
 382             long s = -1;
 383             int ti = -1;
 384             try {
 385                 beginBlocking();
 386                 ti = threads.add();
 387                 if (!isOpen())
 388                     return -1;
 389                 do {
 390                     s = nd.size(fd);
 391                 } while ((s == IOStatus.INTERRUPTED) && isOpen());
 392                 return IOStatus.normalize(s);
 393             } finally {
 394                 threads.remove(ti);
 395                 endBlocking(s > -1);
 396                 assert IOStatus.check(s);
 397             }
 398         }
 399     }
 400 
 401     public FileChannel truncate(long newSize) throws IOException {
 402         ensureOpen();
 403         if (newSize < 0)
 404             throw new IllegalArgumentException("Negative size");
 405         if (!writable)
 406             throw new NonWritableChannelException();
 407         synchronized (positionLock) {
 408             int rv = -1;
 409             long p = -1;
 410             int ti = -1;
 411             long rp = -1;
 412             try {
 413                 beginBlocking();
 414                 ti = threads.add();
 415                 if (!isOpen())
 416                     return null;
 417 
 418                 // get current size
 419                 long size;
 420                 do {
 421                     size = nd.size(fd);
 422                 } while ((size == IOStatus.INTERRUPTED) && isOpen());
 423                 if (!isOpen())
 424                     return null;
 425 
 426                 // get current position
 427                 do {
 428                     p = nd.seek(fd, -1);
 429                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 430                 if (!isOpen())
 431                     return null;
 432                 assert p >= 0;
 433 
 434                 // truncate file if given size is less than the current size
 435                 if (newSize < size) {
 436                     do {
 437                         rv = nd.truncate(fd, newSize);
 438                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
 439                     if (!isOpen())
 440                         return null;
 441                 }
 442 
 443                 // if position is beyond new size then adjust it
 444                 if (p > newSize)
 445                     p = newSize;
 446                 do {
 447                     rp = nd.seek(fd, p);
 448                 } while ((rp == IOStatus.INTERRUPTED) && isOpen());
 449                 return this;
 450             } finally {
 451                 threads.remove(ti);
 452                 endBlocking(rv > -1);
 453                 assert IOStatus.check(rv);
 454             }
 455         }
 456     }
 457 
 458     public void force(boolean metaData) throws IOException {
 459         ensureOpen();
 460         int rv = -1;
 461         int ti = -1;
 462         try {
 463             beginBlocking();
 464             ti = threads.add();
 465             if (!isOpen())
 466                 return;
 467             do {
 468                 rv = nd.force(fd, metaData);




 469             } while ((rv == IOStatus.INTERRUPTED) && isOpen());
 470         } finally {
 471             threads.remove(ti);
 472             endBlocking(rv > -1);
 473             assert IOStatus.check(rv);
 474         }
 475     }
 476 
 477     // Assume at first that the underlying kernel supports sendfile();
 478     // set this to false if we find out later that it doesn't
 479     //
 480     private static volatile boolean transferSupported = true;
 481 
 482     // Assume that the underlying kernel sendfile() will work if the target
 483     // fd is a pipe; set this to false if we find out later that it doesn't
 484     //
 485     private static volatile boolean pipeSupported = true;
 486 
 487     // Assume that the underlying kernel sendfile() will work if the target
 488     // fd is a file; set this to false if we find out later that it doesn't
 489     //
 490     private static volatile boolean fileSupported = true;
 491 
 492     private long transferToDirectlyInternal(long position, int icount,
 493                                             WritableByteChannel target,
 494                                             FileDescriptor targetFD)
 495         throws IOException
 496     {
 497         assert !nd.transferToDirectlyNeedsPositionLock() ||
 498                Thread.holdsLock(positionLock);
 499 
 500         long n = -1;
 501         int ti = -1;
 502         try {
 503             beginBlocking();
 504             ti = threads.add();
 505             if (!isOpen())
 506                 return -1;
 507             do {
 508                 n = transferTo0(fd, position, icount, targetFD);




 509             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 510             if (n == IOStatus.UNSUPPORTED_CASE) {
 511                 if (target instanceof SinkChannelImpl)
 512                     pipeSupported = false;
 513                 if (target instanceof FileChannelImpl)
 514                     fileSupported = false;
 515                 return IOStatus.UNSUPPORTED_CASE;
 516             }
 517             if (n == IOStatus.UNSUPPORTED) {
 518                 // Don't bother trying again
 519                 transferSupported = false;
 520                 return IOStatus.UNSUPPORTED;
 521             }
 522             return IOStatus.normalize(n);
 523         } finally {
 524             threads.remove(ti);
 525             end (n > -1);
 526         }
 527     }
 528 

 819         if (nd.needsPositionLock()) {
 820             synchronized (positionLock) {
 821                 return readInternal(dst, position);
 822             }
 823         } else {
 824             return readInternal(dst, position);
 825         }
 826     }
 827 
 828     private int readInternal(ByteBuffer dst, long position) throws IOException {
 829         assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
 830         int n = 0;
 831         int ti = -1;
 832 
 833         try {
 834             beginBlocking();
 835             ti = threads.add();
 836             if (!isOpen())
 837                 return -1;
 838             do {
 839                 n = IOUtil.read(fd, dst, position, direct, alignment, nd);





 840             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 841             return IOStatus.normalize(n);
 842         } finally {
 843             threads.remove(ti);
 844             endBlocking(n > 0);
 845             assert IOStatus.check(n);
 846         }
 847     }
 848 
 849     public int write(ByteBuffer src, long position) throws IOException {
 850         if (src == null)
 851             throw new NullPointerException();
 852         if (position < 0)
 853             throw new IllegalArgumentException("Negative position");
 854         ensureOpen();
 855         if (!writable)
 856             throw new NonWritableChannelException();
 857         if (direct)
 858             Util.checkChannelPositionAligned(position, alignment);
 859         if (nd.needsPositionLock()) {
 860             synchronized (positionLock) {
 861                 return writeInternal(src, position);
 862             }
 863         } else {
 864             return writeInternal(src, position);
 865         }
 866     }
 867 
 868     private int writeInternal(ByteBuffer src, long position) throws IOException {
 869         assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
 870         int n = 0;
 871         int ti = -1;
 872         try {
 873             beginBlocking();
 874             ti = threads.add();
 875             if (!isOpen())
 876                 return -1;
 877             do {
 878                 n = IOUtil.write(fd, src, position, direct, alignment, nd);





 879             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 880             return IOStatus.normalize(n);
 881         } finally {
 882             threads.remove(ti);
 883             endBlocking(n > 0);
 884             assert IOStatus.check(n);
 885         }
 886     }
 887 
 888 
 889     // -- Memory-mapped buffers --
 890 
 891     private static abstract class Unmapper
 892         implements Runnable, UnmapperProxy
 893     {
 894         // may be required to close file
 895         private static final NativeDispatcher nd = new FileDispatcherImpl();
 896 
 897         private volatile long address;
 898         protected final long size;

1066             throw new IllegalArgumentException("Negative position");
1067         if (size < 0L)
1068             throw new IllegalArgumentException("Negative size");
1069         if (position + size < 0)
1070             throw new IllegalArgumentException("Position + size overflow");
1071 
1072         checkMode(mode, prot, isSync);
1073         long addr = -1;
1074         int ti = -1;
1075         try {
1076             beginBlocking();
1077             ti = threads.add();
1078             if (!isOpen())
1079                 return null;
1080 
1081             long mapSize;
1082             int pagePosition;
1083             synchronized (positionLock) {
1084                 long filesize;
1085                 do {
1086                     filesize = nd.size(fd);
1087                 } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
1088                 if (!isOpen())
1089                     return null;
1090 
1091                 if (filesize < position + size) { // Extend file size
1092                     if (!writable) {
1093                         throw new IOException("Channel not open for writing " +
1094                             "- cannot extend file to required size");
1095                     }
1096                     int rv;
1097                     do {
1098                         rv = nd.truncate(fd, position + size);
1099                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
1100                     if (!isOpen())
1101                         return null;
1102                 }
1103 
1104                 if (size == 0) {
1105                     return null;
1106                 }
1107 
1108                 pagePosition = (int)(position % allocationGranularity);
1109                 long mapPosition = position - pagePosition;
1110                 mapSize = size + pagePosition;
1111                 try {
1112                     // If map0 did not throw an exception, the address is valid
1113                     addr = map0(prot, mapPosition, mapSize, isSync);
1114                 } catch (OutOfMemoryError x) {
1115                     // An OutOfMemoryError may indicate that we've exhausted
1116                     // memory so force gc and re-attempt map
1117                     System.gc();
1118                     try {

1266     public FileLock lock(long position, long size, boolean shared)
1267         throws IOException
1268     {
1269         ensureOpen();
1270         if (shared && !readable)
1271             throw new NonReadableChannelException();
1272         if (!shared && !writable)
1273             throw new NonWritableChannelException();
1274         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1275         FileLockTable flt = fileLockTable();
1276         flt.add(fli);
1277         boolean completed = false;
1278         int ti = -1;
1279         try {
1280             beginBlocking();
1281             ti = threads.add();
1282             if (!isOpen())
1283                 return null;
1284             int n;
1285             do {
1286                 n = nd.lock(fd, true, position, size, shared);




1287             } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
1288             if (isOpen()) {
1289                 if (n == FileDispatcher.RET_EX_LOCK) {
1290                     assert shared;
1291                     FileLockImpl fli2 = new FileLockImpl(this, position, size,
1292                                                          false);
1293                     flt.replace(fli, fli2);
1294                     fli = fli2;
1295                 }
1296                 completed = true;
1297             }
1298         } finally {
1299             if (!completed)
1300                 flt.remove(fli);
1301             threads.remove(ti);
1302             try {
1303                 endBlocking(completed);
1304             } catch (ClosedByInterruptException e) {
1305                 throw new FileLockInterruptionException();
1306             }

  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.lang.ref.Cleaner.Cleanable;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.nio.channels.AsynchronousCloseException;
  35 import java.nio.channels.ClosedByInterruptException;
  36 import java.nio.channels.ClosedChannelException;
  37 import java.nio.channels.FileChannel;
  38 import java.nio.channels.FileLock;
  39 import java.nio.channels.FileLockInterruptionException;
  40 import java.nio.channels.NonReadableChannelException;
  41 import java.nio.channels.NonWritableChannelException;
  42 import java.nio.channels.ReadableByteChannel;
  43 import java.nio.channels.SelectableChannel;
  44 import java.nio.channels.WritableByteChannel;
  45 import java.util.Objects;
  46 
  47 import jdk.internal.access.JavaIOFileDescriptorAccess;
  48 import jdk.internal.access.SharedSecrets;
  49 import jdk.internal.misc.Blocker;
  50 import jdk.internal.misc.ExtendedMapMode;
  51 import jdk.internal.misc.Unsafe;
  52 import jdk.internal.misc.VM;
  53 import jdk.internal.misc.VM.BufferPool;
  54 import jdk.internal.ref.Cleaner;
  55 import jdk.internal.ref.CleanerFactory;
  56 
  57 import jdk.internal.access.foreign.UnmapperProxy;
  58 
  59 public class FileChannelImpl
  60     extends FileChannel
  61 {
  62     // Memory allocation size for mapping buffers
  63     private static final long allocationGranularity;
  64 
  65     // Access to FileDescriptor internals
  66     private static final JavaIOFileDescriptorAccess fdAccess =
  67         SharedSecrets.getJavaIOFileDescriptorAccess();
  68 
  69     // Maximum direct transfer size

 213             fdAccess.close(fd);
 214         }
 215 
 216     }
 217 
 218     public int read(ByteBuffer dst) throws IOException {
 219         ensureOpen();
 220         if (!readable)
 221             throw new NonReadableChannelException();
 222         synchronized (positionLock) {
 223             if (direct)
 224                 Util.checkChannelPositionAligned(position(), alignment);
 225             int n = 0;
 226             int ti = -1;
 227             try {
 228                 beginBlocking();
 229                 ti = threads.add();
 230                 if (!isOpen())
 231                     return 0;
 232                 do {
 233                     if (Thread.currentThread().isVirtual()) {
 234                         n = Blocker.managedBlock(() ->
 235                                 IOUtil.read(fd, dst, -1, direct, alignment, nd));
 236                     } else {
 237                         n = IOUtil.read(fd, dst, -1, direct, alignment, nd);
 238                     }
 239                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 240                 return IOStatus.normalize(n);
 241             } finally {
 242                 threads.remove(ti);
 243                 endBlocking(n > 0);
 244                 assert IOStatus.check(n);
 245             }
 246         }
 247     }
 248 
 249     public long read(ByteBuffer[] dsts, int offset, int length)
 250         throws IOException
 251     {
 252         Objects.checkFromIndexSize(offset, length, dsts.length);
 253         ensureOpen();
 254         if (!readable)
 255             throw new NonReadableChannelException();
 256         synchronized (positionLock) {
 257             if (direct)
 258                 Util.checkChannelPositionAligned(position(), alignment);
 259             long n = 0;
 260             int ti = -1;
 261             try {
 262                 beginBlocking();
 263                 ti = threads.add();
 264                 if (!isOpen())
 265                     return 0;
 266                 do {
 267                     if (Thread.currentThread().isVirtual()) {
 268                         n = Blocker.managedBlock(() ->
 269                                 IOUtil.read(fd, dsts, offset, length, direct, alignment, nd));
 270                     } else {
 271                         n = IOUtil.read(fd, dsts, offset, length, direct, alignment, nd);
 272                     }
 273                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 274                 return IOStatus.normalize(n);
 275             } finally {
 276                 threads.remove(ti);
 277                 endBlocking(n > 0);
 278                 assert IOStatus.check(n);
 279             }
 280         }
 281     }
 282 
 283     public int write(ByteBuffer src) throws IOException {
 284         ensureOpen();
 285         if (!writable)
 286             throw new NonWritableChannelException();
 287         synchronized (positionLock) {
 288             if (direct)
 289                 Util.checkChannelPositionAligned(position(), alignment);
 290             int n = 0;
 291             int ti = -1;
 292             try {
 293                 beginBlocking();
 294                 ti = threads.add();
 295                 if (!isOpen())
 296                     return 0;
 297                 do {
 298                     if (Thread.currentThread().isVirtual()) {
 299                         n = Blocker.managedBlock(() ->
 300                                 IOUtil.write(fd, src, -1, direct, alignment, nd));
 301                     } else {
 302                         n = IOUtil.write(fd, src, -1, direct, alignment, nd);
 303                     }
 304                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 305                 return IOStatus.normalize(n);
 306             } finally {
 307                 threads.remove(ti);
 308                 endBlocking(n > 0);
 309                 assert IOStatus.check(n);
 310             }
 311         }
 312     }
 313 
 314     public long write(ByteBuffer[] srcs, int offset, int length)
 315         throws IOException
 316     {
 317         Objects.checkFromIndexSize(offset, length, srcs.length);
 318         ensureOpen();
 319         if (!writable)
 320             throw new NonWritableChannelException();
 321         synchronized (positionLock) {
 322             if (direct)
 323                 Util.checkChannelPositionAligned(position(), alignment);
 324             long n = 0;
 325             int ti = -1;
 326             try {
 327                 beginBlocking();
 328                 ti = threads.add();
 329                 if (!isOpen())
 330                     return 0;
 331                 do {
 332                     if (Thread.currentThread().isVirtual()) {
 333                         n = Blocker.managedBlock(() ->
 334                                 IOUtil.write(fd, srcs, offset, length, direct, alignment, nd));
 335                     } else {
 336                         n = IOUtil.write(fd, srcs, offset, length, direct, alignment, nd);
 337                     }
 338                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 339                 return IOStatus.normalize(n);
 340             } finally {
 341                 threads.remove(ti);
 342                 endBlocking(n > 0);
 343                 assert IOStatus.check(n);
 344             }
 345         }
 346     }
 347 
 348     // -- Other operations --
 349 
 350     private long lockedSize() throws IOException {
 351         assert Thread.holdsLock(positionLock);
 352         if (Thread.currentThread().isVirtual()) {
 353             return Blocker.managedBlock(() -> nd.size(fd));
 354         } else {
 355             return nd.size(fd);
 356         }
 357     }
 358 
 359     private long lockedSeek(long offset) throws IOException {
 360         assert Thread.holdsLock(positionLock);
 361         if (Thread.currentThread().isVirtual()) {
 362             return Blocker.managedBlock(() -> nd.seek(fd, offset));
 363         } else {
 364             return nd.seek(fd, offset);
 365         }
 366     }
 367 
 368     private int lockedTruncate(long newSize) throws IOException {
 369         assert Thread.holdsLock(positionLock);
 370         if (Thread.currentThread().isVirtual()) {
 371             return Blocker.managedBlock(() -> nd.truncate(fd, newSize));
 372         } else {
 373             return nd.truncate(fd, newSize);
 374         }
 375     }
 376 
 377     public long position() throws IOException {
 378         ensureOpen();
 379         synchronized (positionLock) {
 380             long p = -1;
 381             int ti = -1;
 382             try {
 383                 beginBlocking();
 384                 ti = threads.add();
 385                 if (!isOpen())
 386                     return 0;
 387                 boolean append = fdAccess.getAppend(fd);
 388                 do {
 389                     // in append-mode then position is advanced to end before writing
 390                     p = (append) ? lockedSize() : lockedSeek(-1);
 391                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 392                 return IOStatus.normalize(p);
 393             } finally {
 394                 threads.remove(ti);
 395                 endBlocking(p > -1);
 396                 assert IOStatus.check(p);
 397             }
 398         }
 399     }
 400 
 401     public FileChannel position(long newPosition) throws IOException {
 402         ensureOpen();
 403         if (newPosition < 0)
 404             throw new IllegalArgumentException();
 405         synchronized (positionLock) {
 406             long p = -1;
 407             int ti = -1;
 408             try {
 409                 beginBlocking();
 410                 ti = threads.add();
 411                 if (!isOpen())
 412                     return null;
 413                 do {
 414                     p = lockedSeek(newPosition);
 415                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 416                 return this;
 417             } finally {
 418                 threads.remove(ti);
 419                 endBlocking(p > -1);
 420                 assert IOStatus.check(p);
 421             }
 422         }
 423     }
 424 
 425     public long size() throws IOException {
 426         ensureOpen();
 427         synchronized (positionLock) {
 428             long s = -1;
 429             int ti = -1;
 430             try {
 431                 beginBlocking();
 432                 ti = threads.add();
 433                 if (!isOpen())
 434                     return -1;
 435                 do {
 436                     s = lockedSize();
 437                 } while ((s == IOStatus.INTERRUPTED) && isOpen());
 438                 return IOStatus.normalize(s);
 439             } finally {
 440                 threads.remove(ti);
 441                 endBlocking(s > -1);
 442                 assert IOStatus.check(s);
 443             }
 444         }
 445     }
 446 
 447     public FileChannel truncate(long newSize) throws IOException {
 448         ensureOpen();
 449         if (newSize < 0)
 450             throw new IllegalArgumentException("Negative size");
 451         if (!writable)
 452             throw new NonWritableChannelException();
 453         synchronized (positionLock) {
 454             int rv = -1;
 455             long p = -1;
 456             int ti = -1;
 457             long rp = -1;
 458             try {
 459                 beginBlocking();
 460                 ti = threads.add();
 461                 if (!isOpen())
 462                     return null;
 463 
 464                 // get current size
 465                 long size;
 466                 do {
 467                     size = lockedSize();
 468                 } while ((size == IOStatus.INTERRUPTED) && isOpen());
 469                 if (!isOpen())
 470                     return null;
 471 
 472                 // get current position
 473                 do {
 474                     p = lockedSeek(-1);
 475                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
 476                 if (!isOpen())
 477                     return null;
 478                 assert p >= 0;
 479 
 480                 // truncate file if given size is less than the current size
 481                 if (newSize < size) {
 482                     do {
 483                         rv = lockedTruncate(newSize);
 484                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
 485                     if (!isOpen())
 486                         return null;
 487                 }
 488 
 489                 // if position is beyond new size then adjust it
 490                 if (p > newSize)
 491                     p = newSize;
 492                 do {
 493                     rp = lockedSeek(p);
 494                 } while ((rp == IOStatus.INTERRUPTED) && isOpen());
 495                 return this;
 496             } finally {
 497                 threads.remove(ti);
 498                 endBlocking(rv > -1);
 499                 assert IOStatus.check(rv);
 500             }
 501         }
 502     }
 503 
 504     public void force(boolean metaData) throws IOException {
 505         ensureOpen();
 506         int rv = -1;
 507         int ti = -1;
 508         try {
 509             beginBlocking();
 510             ti = threads.add();
 511             if (!isOpen())
 512                 return;
 513             do {
 514                 if (Thread.currentThread().isVirtual()) {
 515                     rv = Blocker.managedBlock(() -> nd.force(fd, metaData));
 516                 } else {
 517                     rv = nd.force(fd, metaData);
 518                 }
 519             } while ((rv == IOStatus.INTERRUPTED) && isOpen());
 520         } finally {
 521             threads.remove(ti);
 522             endBlocking(rv > -1);
 523             assert IOStatus.check(rv);
 524         }
 525     }
 526 
 527     // Assume at first that the underlying kernel supports sendfile();
 528     // set this to false if we find out later that it doesn't
 529     //
 530     private static volatile boolean transferSupported = true;
 531 
 532     // Assume that the underlying kernel sendfile() will work if the target
 533     // fd is a pipe; set this to false if we find out later that it doesn't
 534     //
 535     private static volatile boolean pipeSupported = true;
 536 
 537     // Assume that the underlying kernel sendfile() will work if the target
 538     // fd is a file; set this to false if we find out later that it doesn't
 539     //
 540     private static volatile boolean fileSupported = true;
 541 
 542     private long transferToDirectlyInternal(long position, int icount,
 543                                             WritableByteChannel target,
 544                                             FileDescriptor targetFD)
 545         throws IOException
 546     {
 547         assert !nd.transferToDirectlyNeedsPositionLock() ||
 548                Thread.holdsLock(positionLock);
 549 
 550         long n = -1;
 551         int ti = -1;
 552         try {
 553             beginBlocking();
 554             ti = threads.add();
 555             if (!isOpen())
 556                 return -1;
 557             do {
 558                 if (Thread.currentThread().isVirtual()) {
 559                     n = Blocker.managedBlock(() -> transferTo0(fd, position, icount, targetFD));
 560                 } else {
 561                     n = transferTo0(fd, position, icount, targetFD);
 562                 }
 563             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 564             if (n == IOStatus.UNSUPPORTED_CASE) {
 565                 if (target instanceof SinkChannelImpl)
 566                     pipeSupported = false;
 567                 if (target instanceof FileChannelImpl)
 568                     fileSupported = false;
 569                 return IOStatus.UNSUPPORTED_CASE;
 570             }
 571             if (n == IOStatus.UNSUPPORTED) {
 572                 // Don't bother trying again
 573                 transferSupported = false;
 574                 return IOStatus.UNSUPPORTED;
 575             }
 576             return IOStatus.normalize(n);
 577         } finally {
 578             threads.remove(ti);
 579             end (n > -1);
 580         }
 581     }
 582 

 873         if (nd.needsPositionLock()) {
 874             synchronized (positionLock) {
 875                 return readInternal(dst, position);
 876             }
 877         } else {
 878             return readInternal(dst, position);
 879         }
 880     }
 881 
 882     private int readInternal(ByteBuffer dst, long position) throws IOException {
 883         assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
 884         int n = 0;
 885         int ti = -1;
 886 
 887         try {
 888             beginBlocking();
 889             ti = threads.add();
 890             if (!isOpen())
 891                 return -1;
 892             do {
 893                 if (Thread.currentThread().isVirtual()) {
 894                     n = Blocker.managedBlock(() ->
 895                             IOUtil.read(fd, dst, position, direct, alignment, nd));
 896                 } else {
 897                     n = IOUtil.read(fd, dst, position, direct, alignment, nd);
 898                 }
 899             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 900             return IOStatus.normalize(n);
 901         } finally {
 902             threads.remove(ti);
 903             endBlocking(n > 0);
 904             assert IOStatus.check(n);
 905         }
 906     }
 907 
 908     public int write(ByteBuffer src, long position) throws IOException {
 909         if (src == null)
 910             throw new NullPointerException();
 911         if (position < 0)
 912             throw new IllegalArgumentException("Negative position");
 913         ensureOpen();
 914         if (!writable)
 915             throw new NonWritableChannelException();
 916         if (direct)
 917             Util.checkChannelPositionAligned(position, alignment);
 918         if (nd.needsPositionLock()) {
 919             synchronized (positionLock) {
 920                 return writeInternal(src, position);
 921             }
 922         } else {
 923             return writeInternal(src, position);
 924         }
 925     }
 926 
 927     private int writeInternal(ByteBuffer src, long position) throws IOException {
 928         assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
 929         int n = 0;
 930         int ti = -1;
 931         try {
 932             beginBlocking();
 933             ti = threads.add();
 934             if (!isOpen())
 935                 return -1;
 936             do {
 937                 if (Thread.currentThread().isVirtual()) {
 938                     n = Blocker.managedBlock(() ->
 939                             IOUtil.write(fd, src, position, direct, alignment, nd));
 940                 } else {
 941                     n = IOUtil.write(fd, src, position, direct, alignment, nd);
 942                 }
 943             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 944             return IOStatus.normalize(n);
 945         } finally {
 946             threads.remove(ti);
 947             endBlocking(n > 0);
 948             assert IOStatus.check(n);
 949         }
 950     }
 951 
 952 
 953     // -- Memory-mapped buffers --
 954 
 955     private static abstract class Unmapper
 956         implements Runnable, UnmapperProxy
 957     {
 958         // may be required to close file
 959         private static final NativeDispatcher nd = new FileDispatcherImpl();
 960 
 961         private volatile long address;
 962         protected final long size;

1130             throw new IllegalArgumentException("Negative position");
1131         if (size < 0L)
1132             throw new IllegalArgumentException("Negative size");
1133         if (position + size < 0)
1134             throw new IllegalArgumentException("Position + size overflow");
1135 
1136         checkMode(mode, prot, isSync);
1137         long addr = -1;
1138         int ti = -1;
1139         try {
1140             beginBlocking();
1141             ti = threads.add();
1142             if (!isOpen())
1143                 return null;
1144 
1145             long mapSize;
1146             int pagePosition;
1147             synchronized (positionLock) {
1148                 long filesize;
1149                 do {
1150                     filesize = lockedSize();
1151                 } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
1152                 if (!isOpen())
1153                     return null;
1154 
1155                 if (filesize < position + size) { // Extend file size
1156                     if (!writable) {
1157                         throw new IOException("Channel not open for writing " +
1158                             "- cannot extend file to required size");
1159                     }
1160                     int rv;
1161                     do {
1162                         rv = lockedTruncate(position + size);
1163                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
1164                     if (!isOpen())
1165                         return null;
1166                 }
1167 
1168                 if (size == 0) {
1169                     return null;
1170                 }
1171 
1172                 pagePosition = (int)(position % allocationGranularity);
1173                 long mapPosition = position - pagePosition;
1174                 mapSize = size + pagePosition;
1175                 try {
1176                     // If map0 did not throw an exception, the address is valid
1177                     addr = map0(prot, mapPosition, mapSize, isSync);
1178                 } catch (OutOfMemoryError x) {
1179                     // An OutOfMemoryError may indicate that we've exhausted
1180                     // memory so force gc and re-attempt map
1181                     System.gc();
1182                     try {

1330     public FileLock lock(long position, long size, boolean shared)
1331         throws IOException
1332     {
1333         ensureOpen();
1334         if (shared && !readable)
1335             throw new NonReadableChannelException();
1336         if (!shared && !writable)
1337             throw new NonWritableChannelException();
1338         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1339         FileLockTable flt = fileLockTable();
1340         flt.add(fli);
1341         boolean completed = false;
1342         int ti = -1;
1343         try {
1344             beginBlocking();
1345             ti = threads.add();
1346             if (!isOpen())
1347                 return null;
1348             int n;
1349             do {
1350                 if (Thread.currentThread().isVirtual()) {
1351                     n = Blocker.managedBlock(() -> nd.lock(fd, true, position, size, shared));
1352                 } else {
1353                     n = nd.lock(fd, true, position, size, shared);
1354                 }
1355             } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
1356             if (isOpen()) {
1357                 if (n == FileDispatcher.RET_EX_LOCK) {
1358                     assert shared;
1359                     FileLockImpl fli2 = new FileLockImpl(this, position, size,
1360                                                          false);
1361                     flt.replace(fli, fli2);
1362                     fli = fli2;
1363                 }
1364                 completed = true;
1365             }
1366         } finally {
1367             if (!completed)
1368                 flt.remove(fli);
1369             threads.remove(ti);
1370             try {
1371                 endBlocking(completed);
1372             } catch (ClosedByInterruptException e) {
1373                 throw new FileLockInterruptionException();
1374             }
< prev index next >