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
|