< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.nio.ByteBuffer;
  31 import java.nio.MappedByteBuffer;
  32 import java.nio.channels.ClosedByInterruptException;
  33 import java.nio.channels.ClosedChannelException;
  34 import java.nio.channels.FileChannel;
  35 import java.nio.channels.FileLock;
  36 import java.nio.channels.FileLockInterruptionException;
  37 import java.nio.channels.NonReadableChannelException;
  38 import java.nio.channels.NonWritableChannelException;
  39 import java.nio.channels.OverlappingFileLockException;
  40 import java.nio.channels.ReadableByteChannel;
  41 import java.nio.channels.SelectableChannel;
  42 import java.nio.channels.WritableByteChannel;
  43 import java.util.ArrayList;
  44 import java.util.List;

  45 
  46 import jdk.internal.misc.JavaIOFileDescriptorAccess;
  47 import jdk.internal.misc.JavaNioAccess;
  48 import jdk.internal.misc.SharedSecrets;
  49 import jdk.internal.ref.Cleaner;
  50 import sun.security.action.GetPropertyAction;
  51 
  52 public class FileChannelImpl
  53     extends FileChannel
  54 {
  55     // Memory allocation size for mapping buffers
  56     private static final long allocationGranularity;
  57 
  58     // Access to FileDispatcher internals
  59     private static final JavaIOFileDescriptorAccess fdAccess =
  60         SharedSecrets.getJavaIOFileDescriptorAccess();
  61 
  62     // Used to make native read and write calls
  63     private final FileDispatcher nd;
  64 


 115     }
 116 
 117     // -- Standard channel operations --
 118 
 119     protected void implCloseChannel() throws IOException {
 120         if (!fd.valid())
 121             return; // nothing to do
 122 
 123         // Release and invalidate any locks that we still hold
 124         if (fileLockTable != null) {
 125             for (FileLock fl: fileLockTable.removeAll()) {
 126                 synchronized (fl) {
 127                     if (fl.isValid()) {
 128                         nd.release(fd, fl.position(), fl.size());
 129                         ((FileLockImpl)fl).invalidate();
 130                     }
 131                 }
 132             }
 133         }
 134 












 135         // signal any threads blocked on this channel
 136         threads.signalAndWait();
 137 
 138         if (parent != null) {
 139 
 140             // Close the fd via the parent stream's close method.  The parent
 141             // will reinvoke our close method, which is defined in the
 142             // superclass AbstractInterruptibleChannel, but the isOpen logic in
 143             // that method will prevent this method from being reinvoked.
 144             //
 145             ((java.io.Closeable)parent).close();
 146         } else {
 147             nd.close(fd);
 148         }
 149 
 150     }
 151 
 152     public int read(ByteBuffer dst) throws IOException {
 153         ensureOpen();
 154         if (!readable)


1003             public long getMemoryUsed() {
1004                 return Unmapper.totalSize;
1005             }
1006         };
1007     }
1008 
1009     // -- Locks --
1010 
1011 
1012 
1013     // keeps track of locks on this file
1014     private volatile FileLockTable fileLockTable;
1015 
1016     // indicates if file locks are maintained system-wide (as per spec)
1017     private static boolean isSharedFileLockTable;
1018 
1019     // indicates if the disableSystemWideOverlappingFileLockCheck property
1020     // has been checked
1021     private static volatile boolean propertyChecked;
1022 



1023     // The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so
1024     // the overlap check wasn't system wide when there were multiple channels to
1025     // the same file. This property is used to get 1.4/5.0 behavior if desired.
1026     private static boolean isSharedFileLockTable() {
1027         if (!propertyChecked) {
1028             synchronized (FileChannelImpl.class) {
1029                 if (!propertyChecked) {
1030                     String value = GetPropertyAction.privilegedGetProperty(
1031                             "sun.nio.ch.disableSystemWideOverlappingFileLockCheck");
1032                     isSharedFileLockTable = ((value == null) || value.equals("false"));
1033                     propertyChecked = true;
1034                 }
1035             }
1036         }
1037         return isSharedFileLockTable;
1038     }
1039 
1040     private FileLockTable fileLockTable() throws IOException {
1041         if (fileLockTable == null) {
1042             synchronized (this) {
1043                 if (fileLockTable == null) {
1044                     if (isSharedFileLockTable()) {
1045                         int ti = threads.add();
1046                         try {
1047                             ensureOpen();
1048                             fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
1049                         } finally {
1050                             threads.remove(ti);
1051                         }
1052                     } else {
1053                         fileLockTable = new SimpleFileLockTable();
1054                     }
1055                 }
1056             }
1057         }
1058         return fileLockTable;
1059     }
1060 











1061     public FileLock lock(long position, long size, boolean shared)
1062         throws IOException
1063     {
1064         ensureOpen();
1065         if (shared && !readable)
1066             throw new NonReadableChannelException();
1067         if (!shared && !writable)
1068             throw new NonWritableChannelException();
1069         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1070         FileLockTable flt = fileLockTable();
1071         flt.add(fli);


1072         boolean completed = false;
1073         int ti = -1;
1074         try {
1075             begin();
1076             ti = threads.add();
1077             if (!isOpen())
1078                 return null;
1079             int n;
1080             do {
1081                 n = nd.lock(fd, true, position, size, shared);
1082             } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
1083             if (isOpen()) {
1084                 if (n == FileDispatcher.RET_EX_LOCK) {
1085                     assert shared;
1086                     FileLockImpl fli2 = new FileLockImpl(this, position, size,
1087                                                          false);
1088                     flt.replace(fli, fli2);

1089                     fli = fli2;

1090                 }
1091                 completed = true;
1092             }
1093         } finally {
1094             if (!completed)
1095                 flt.remove(fli);


1096             threads.remove(ti);
1097             try {
1098                 end(completed);
1099             } catch (ClosedByInterruptException e) {
1100                 throw new FileLockInterruptionException();
1101             }
1102         }
1103         return fli;
1104     }
1105 
1106     public FileLock tryLock(long position, long size, boolean shared)
1107         throws IOException
1108     {
1109         ensureOpen();
1110         if (shared && !readable)
1111             throw new NonReadableChannelException();
1112         if (!shared && !writable)
1113             throw new NonWritableChannelException();
1114         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1115         FileLockTable flt = fileLockTable();
1116         flt.add(fli);


1117         int result;
1118 
1119         int ti = threads.add();
1120         try {
1121             try {
1122                 ensureOpen();
1123                 result = nd.lock(fd, false, position, size, shared);
1124             } catch (IOException e) {
1125                 flt.remove(fli);

1126                 throw e;
1127             }
1128             if (result == FileDispatcher.NO_LOCK) {
1129                 flt.remove(fli);

1130                 return null;
1131             }
1132             if (result == FileDispatcher.RET_EX_LOCK) {
1133                 assert shared;
1134                 FileLockImpl fli2 = new FileLockImpl(this, position, size,
1135                                                      false);
1136                 flt.replace(fli, fli2);


1137                 return fli2;
1138             }
1139             return fli;
1140         } finally {
1141             threads.remove(ti);
1142         }
1143     }
1144 
1145     void release(FileLockImpl fli) throws IOException {
1146         int ti = threads.add();
1147         try {
1148             ensureOpen();
1149             nd.release(fd, fli.position(), fli.size());
1150         } finally {
1151             threads.remove(ti);
1152         }
1153         assert fileLockTable != null;
1154         fileLockTable.remove(fli);
1155     }
1156 


   1 /*
   2  * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.nio.ByteBuffer;
  31 import java.nio.MappedByteBuffer;
  32 import java.nio.channels.ClosedByInterruptException;
  33 import java.nio.channels.ClosedChannelException;
  34 import java.nio.channels.FileChannel;
  35 import java.nio.channels.FileLock;
  36 import java.nio.channels.FileLockInterruptionException;
  37 import java.nio.channels.NonReadableChannelException;
  38 import java.nio.channels.NonWritableChannelException;
  39 import java.nio.channels.OverlappingFileLockException;
  40 import java.nio.channels.ReadableByteChannel;
  41 import java.nio.channels.SelectableChannel;
  42 import java.nio.channels.WritableByteChannel;
  43 import java.util.ArrayList;
  44 import java.util.List;
  45 import java.util.concurrent.CopyOnWriteArrayList;
  46 
  47 import jdk.internal.misc.JavaIOFileDescriptorAccess;
  48 import jdk.internal.misc.JavaNioAccess;
  49 import jdk.internal.misc.SharedSecrets;
  50 import jdk.internal.ref.Cleaner;
  51 import sun.security.action.GetPropertyAction;
  52 
  53 public class FileChannelImpl
  54     extends FileChannel
  55 {
  56     // Memory allocation size for mapping buffers
  57     private static final long allocationGranularity;
  58 
  59     // Access to FileDispatcher internals
  60     private static final JavaIOFileDescriptorAccess fdAccess =
  61         SharedSecrets.getJavaIOFileDescriptorAccess();
  62 
  63     // Used to make native read and write calls
  64     private final FileDispatcher nd;
  65 


 116     }
 117 
 118     // -- Standard channel operations --
 119 
 120     protected void implCloseChannel() throws IOException {
 121         if (!fd.valid())
 122             return; // nothing to do
 123 
 124         // Release and invalidate any locks that we still hold
 125         if (fileLockTable != null) {
 126             for (FileLock fl: fileLockTable.removeAll()) {
 127                 synchronized (fl) {
 128                     if (fl.isValid()) {
 129                         nd.release(fd, fl.position(), fl.size());
 130                         ((FileLockImpl)fl).invalidate();
 131                     }
 132                 }
 133             }
 134         }
 135 
 136         // Release and invalidate any orphaned locks still held
 137         if (fileLockStates != null) {
 138             for (FileLockState fls : fileLockStates) {
 139                 synchronized (fls) {
 140                     if (fls.isValid()) {
 141                         nd.release(fd, fls.position, fls.size);
 142                         fls.invalidate();
 143                     }
 144                 }
 145             }
 146         }
 147 
 148         // signal any threads blocked on this channel
 149         threads.signalAndWait();
 150 
 151         if (parent != null) {
 152 
 153             // Close the fd via the parent stream's close method.  The parent
 154             // will reinvoke our close method, which is defined in the
 155             // superclass AbstractInterruptibleChannel, but the isOpen logic in
 156             // that method will prevent this method from being reinvoked.
 157             //
 158             ((java.io.Closeable)parent).close();
 159         } else {
 160             nd.close(fd);
 161         }
 162 
 163     }
 164 
 165     public int read(ByteBuffer dst) throws IOException {
 166         ensureOpen();
 167         if (!readable)


1016             public long getMemoryUsed() {
1017                 return Unmapper.totalSize;
1018             }
1019         };
1020     }
1021 
1022     // -- Locks --
1023 
1024 
1025 
1026     // keeps track of locks on this file
1027     private volatile FileLockTable fileLockTable;
1028 
1029     // indicates if file locks are maintained system-wide (as per spec)
1030     private static boolean isSharedFileLockTable;
1031 
1032     // indicates if the disableSystemWideOverlappingFileLockCheck property
1033     // has been checked
1034     private static volatile boolean propertyChecked;
1035 
1036     // States of locks acquired on the channel
1037     private volatile List<FileLockState> fileLockStates;
1038 
1039     // The lock list in J2SE 1.4/5.0 was local to each FileChannel instance so
1040     // the overlap check wasn't system wide when there were multiple channels to
1041     // the same file. This property is used to get 1.4/5.0 behavior if desired.
1042     private static boolean isSharedFileLockTable() {
1043         if (!propertyChecked) {
1044             synchronized (FileChannelImpl.class) {
1045                 if (!propertyChecked) {
1046                     String value = GetPropertyAction.privilegedGetProperty(
1047                             "sun.nio.ch.disableSystemWideOverlappingFileLockCheck");
1048                     isSharedFileLockTable = ((value == null) || value.equals("false"));
1049                     propertyChecked = true;
1050                 }
1051             }
1052         }
1053         return isSharedFileLockTable;
1054     }
1055 
1056     private FileLockTable fileLockTable() throws IOException {
1057         if (fileLockTable == null) {
1058             synchronized (this) {
1059                 if (fileLockTable == null) {
1060                     if (isSharedFileLockTable()) {
1061                         int ti = threads.add();
1062                         try {
1063                             ensureOpen();
1064                             fileLockTable = FileLockTable.newSharedFileLockTable(this, fd);
1065                         } finally {
1066                             threads.remove(ti);
1067                         }
1068                     } else {
1069                         fileLockTable = new SimpleFileLockTable();
1070                     }
1071                 }
1072             }
1073         }
1074         return fileLockTable;
1075     }
1076 
1077     private List<FileLockState> fileLockStates() {
1078         if (fileLockStates == null) {
1079             synchronized (this) {
1080                 if (fileLockStates == null) {
1081                     fileLockStates = new CopyOnWriteArrayList<FileLockState>();
1082                 }
1083             }
1084         }
1085         return fileLockStates;
1086     }
1087 
1088     public FileLock lock(long position, long size, boolean shared)
1089         throws IOException
1090     {
1091         ensureOpen();
1092         if (shared && !readable)
1093             throw new NonReadableChannelException();
1094         if (!shared && !writable)
1095             throw new NonWritableChannelException();
1096         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1097         FileLockTable flt = fileLockTable();
1098         flt.add(fli);
1099         List<FileLockState> fls = fileLockStates();
1100         fls.add(fli.getState());
1101         boolean completed = false;
1102         int ti = -1;
1103         try {
1104             begin();
1105             ti = threads.add();
1106             if (!isOpen())
1107                 return null;
1108             int n;
1109             do {
1110                 n = nd.lock(fd, true, position, size, shared);
1111             } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
1112             if (isOpen()) {
1113                 if (n == FileDispatcher.RET_EX_LOCK) {
1114                     assert shared;
1115                     FileLockImpl fli2 = new FileLockImpl(this, position, size,
1116                                                          false);
1117                     flt.replace(fli, fli2);
1118                     fls.remove(fli.getState());
1119                     fli = fli2;
1120                     fls.add(fli.getState());
1121                 }
1122                 completed = true;
1123             }
1124         } finally {
1125             if (!completed) {
1126                 flt.remove(fli);
1127                 fls.remove(fli.getState());
1128             }
1129             threads.remove(ti);
1130             try {
1131                 end(completed);
1132             } catch (ClosedByInterruptException e) {
1133                 throw new FileLockInterruptionException();
1134             }
1135         }
1136         return fli;
1137     }
1138 
1139     public FileLock tryLock(long position, long size, boolean shared)
1140         throws IOException
1141     {
1142         ensureOpen();
1143         if (shared && !readable)
1144             throw new NonReadableChannelException();
1145         if (!shared && !writable)
1146             throw new NonWritableChannelException();
1147         FileLockImpl fli = new FileLockImpl(this, position, size, shared);
1148         FileLockTable flt = fileLockTable();
1149         flt.add(fli);
1150         List<FileLockState> fls = fileLockStates();
1151         fls.add(fli.getState());
1152         int result;
1153 
1154         int ti = threads.add();
1155         try {
1156             try {
1157                 ensureOpen();
1158                 result = nd.lock(fd, false, position, size, shared);
1159             } catch (IOException e) {
1160                 flt.remove(fli);
1161                 fls.remove(fli.getState());
1162                 throw e;
1163             }
1164             if (result == FileDispatcher.NO_LOCK) {
1165                 flt.remove(fli);
1166                 fls.remove(fli.getState());
1167                 return null;
1168             }
1169             if (result == FileDispatcher.RET_EX_LOCK) {
1170                 assert shared;
1171                 FileLockImpl fli2 = new FileLockImpl(this, position, size,
1172                                                      false);
1173                 flt.replace(fli, fli2);
1174                 fls.remove(fli.getState());
1175                 fls.add(fli2.getState());
1176                 return fli2;
1177             }
1178             return fli;
1179         } finally {
1180             threads.remove(ti);
1181         }
1182     }
1183 
1184     void release(FileLockImpl fli) throws IOException {
1185         int ti = threads.add();
1186         try {
1187             ensureOpen();
1188             nd.release(fd, fli.position(), fli.size());
1189         } finally {
1190             threads.remove(ti);
1191         }
1192         assert fileLockTable != null;
1193         fileLockTable.remove(fli);
1194     }
1195 


< prev index next >