1 /* 2 * Copyright (c) 2008, 2009, 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 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.nio.ByteBuffer; 29 import java.nio.channels.*; 30 import java.util.concurrent.ExecutorService; 31 import java.util.concurrent.Future; 32 import java.util.concurrent.locks.*; 33 import java.io.FileDescriptor; 34 import java.io.IOException; 35 36 /** 37 * Base implementation of AsynchronousFileChannel. 38 */ 39 40 abstract class AsynchronousFileChannelImpl 41 extends AsynchronousFileChannel 42 { 43 // close support 44 protected final ReadWriteLock closeLock = new ReentrantReadWriteLock(); 45 protected volatile boolean closed; 46 47 // file descriptor 48 protected final FileDescriptor fdObj; 49 50 // indicates if open for reading/writing 51 protected final boolean reading; 52 protected final boolean writing; 53 54 // associated Executor 55 protected final ExecutorService executor; 56 AsynchronousFileChannelImpl(FileDescriptor fdObj, boolean reading, boolean writing, ExecutorService executor)57 protected AsynchronousFileChannelImpl(FileDescriptor fdObj, 58 boolean reading, 59 boolean writing, 60 ExecutorService executor) 61 { 62 this.fdObj = fdObj; 63 this.reading = reading; 64 this.writing = writing; 65 this.executor = executor; 66 } 67 executor()68 final ExecutorService executor() { 69 return executor; 70 } 71 72 @Override isOpen()73 public final boolean isOpen() { 74 return !closed; 75 } 76 77 /** 78 * Marks the beginning of an I/O operation. 79 * 80 * @throws ClosedChannelException If channel is closed 81 */ begin()82 protected final void begin() throws IOException { 83 closeLock.readLock().lock(); 84 if (closed) 85 throw new ClosedChannelException(); 86 } 87 88 /** 89 * Marks the end of an I/O operation. 90 */ end()91 protected final void end() { 92 closeLock.readLock().unlock(); 93 } 94 95 /** 96 * Marks end of I/O operation 97 */ end(boolean completed)98 protected final void end(boolean completed) throws IOException { 99 end(); 100 if (!completed && !isOpen()) 101 throw new AsynchronousCloseException(); 102 } 103 104 // -- file locking -- 105 implLock(long position, long size, boolean shared, A attachment, CompletionHandler<FileLock,? super A> handler)106 abstract <A> Future<FileLock> implLock(long position, 107 long size, 108 boolean shared, 109 A attachment, 110 CompletionHandler<FileLock,? super A> handler); 111 112 @Override lock(long position, long size, boolean shared)113 public final Future<FileLock> lock(long position, 114 long size, 115 boolean shared) 116 117 { 118 return implLock(position, size, shared, null, null); 119 } 120 121 @Override lock(long position, long size, boolean shared, A attachment, CompletionHandler<FileLock,? super A> handler)122 public final <A> void lock(long position, 123 long size, 124 boolean shared, 125 A attachment, 126 CompletionHandler<FileLock,? super A> handler) 127 { 128 if (handler == null) 129 throw new NullPointerException("'handler' is null"); 130 implLock(position, size, shared, attachment, handler); 131 } 132 133 private volatile FileLockTable fileLockTable; 134 ensureFileLockTableInitialized()135 final void ensureFileLockTableInitialized() throws IOException { 136 if (fileLockTable == null) { 137 synchronized (this) { 138 if (fileLockTable == null) { 139 fileLockTable = FileLockTable.newSharedFileLockTable(this, fdObj); 140 } 141 } 142 } 143 } 144 invalidateAllLocks()145 final void invalidateAllLocks() throws IOException { 146 if (fileLockTable != null) { 147 for (FileLock fl: fileLockTable.removeAll()) { 148 synchronized (fl) { 149 if (fl.isValid()) { 150 FileLockImpl fli = (FileLockImpl)fl; 151 implRelease(fli); 152 fli.invalidate(); 153 } 154 } 155 } 156 } 157 } 158 159 /** 160 * Adds region to lock table 161 */ addToFileLockTable(long position, long size, boolean shared)162 protected final FileLockImpl addToFileLockTable(long position, long size, boolean shared) { 163 final FileLockImpl fli; 164 try { 165 // like begin() but returns null instead of exception 166 closeLock.readLock().lock(); 167 if (closed) 168 return null; 169 170 try { 171 ensureFileLockTableInitialized(); 172 } catch (IOException x) { 173 // should not happen 174 throw new AssertionError(x); 175 } 176 fli = new FileLockImpl(this, position, size, shared); 177 // may throw OverlappedFileLockException 178 fileLockTable.add(fli); 179 } finally { 180 end(); 181 } 182 return fli; 183 } 184 removeFromFileLockTable(FileLockImpl fli)185 protected final void removeFromFileLockTable(FileLockImpl fli) { 186 fileLockTable.remove(fli); 187 } 188 189 /** 190 * Releases the given file lock. 191 */ implRelease(FileLockImpl fli)192 protected abstract void implRelease(FileLockImpl fli) throws IOException; 193 194 /** 195 * Invoked by FileLockImpl to release the given file lock and remove it 196 * from the lock table. 197 */ release(FileLockImpl fli)198 final void release(FileLockImpl fli) throws IOException { 199 try { 200 begin(); 201 implRelease(fli); 202 removeFromFileLockTable(fli); 203 } finally { 204 end(); 205 } 206 } 207 208 209 // -- reading and writing -- 210 implRead(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer,? super A> handler)211 abstract <A> Future<Integer> implRead(ByteBuffer dst, 212 long position, 213 A attachment, 214 CompletionHandler<Integer,? super A> handler); 215 216 @Override read(ByteBuffer dst, long position)217 public final Future<Integer> read(ByteBuffer dst, long position) { 218 return implRead(dst, position, null, null); 219 } 220 221 @Override read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer,? super A> handler)222 public final <A> void read(ByteBuffer dst, 223 long position, 224 A attachment, 225 CompletionHandler<Integer,? super A> handler) 226 { 227 if (handler == null) 228 throw new NullPointerException("'handler' is null"); 229 implRead(dst, position, attachment, handler); 230 } 231 implWrite(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler)232 abstract <A> Future<Integer> implWrite(ByteBuffer src, 233 long position, 234 A attachment, 235 CompletionHandler<Integer,? super A> handler); 236 237 238 @Override write(ByteBuffer src, long position)239 public final Future<Integer> write(ByteBuffer src, long position) { 240 return implWrite(src, position, null, null); 241 } 242 243 @Override write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler)244 public final <A> void write(ByteBuffer src, 245 long position, 246 A attachment, 247 CompletionHandler<Integer,? super A> handler) 248 { 249 if (handler == null) 250 throw new NullPointerException("'handler' is null"); 251 implWrite(src, position, attachment, handler); 252 } 253 } 254