1e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera/*
2e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera *
5e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * This code is free software; you can redistribute it and/or modify it
6e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * under the terms of the GNU General Public License version 2 only, as
7e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * published by the Free Software Foundation.  Oracle designates this
8e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * particular file as subject to the "Classpath" exception as provided
9e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * by Oracle in the LICENSE file that accompanied this code.
10e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera *
11e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * This code is distributed in the hope that it will be useful, but WITHOUT
12e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * version 2 for more details (a copy is included in the LICENSE file that
15e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * accompanied this code).
16e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera *
17e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * You should have received a copy of the GNU General Public License version
18e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * 2 along with this work; if not, write to the Free Software Foundation,
19e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera *
21e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * or visit www.oracle.com if you need additional information or have any
23e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * questions.
24e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */
25e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
26e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmerapackage sun.nio.ch;
27e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
28e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.nio.channels.*;
29e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.util.concurrent.*;
30e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.nio.ByteBuffer;
31e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.security.AccessController;
32e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.security.PrivilegedAction;
33e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.io.FileDescriptor;
34e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmeraimport java.io.IOException;
35e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
36e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera/**
37e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * "Portable" implementation of AsynchronousFileChannel for use on operating
38e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera * systems that don't support asynchronous file I/O.
39e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera */
40e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
41e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmerapublic class SimpleAsynchronousFileChannelImpl
42e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    extends AsynchronousFileChannelImpl
43e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera{
44e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    // lazy initialization of default thread pool for file I/O
45e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    private static class DefaultExecutorHolder {
46e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        static final ExecutorService defaultExecutor =
47e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            ThreadPool.createDefault().executor();
48e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
49e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
50e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    // Used to make native read and write calls
51e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    private static final FileDispatcher nd = new FileDispatcherImpl();
52e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
53e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    // Thread-safe set of IDs of native threads, for signalling
54e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    private final NativeThreadSet threads = new NativeThreadSet(2);
55e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
56e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
57e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
58e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                      boolean reading,
59e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                      boolean writing,
60e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                      ExecutorService executor)
61e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
62e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        super(fdObj, reading, writing, executor);
63e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
64e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
65e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public static AsynchronousFileChannel open(FileDescriptor fdo,
66e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                               boolean reading,
67e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                               boolean writing,
68e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                               ThreadPool pool)
69e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
70e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // Executor is either default or based on pool parameters
71e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        ExecutorService executor = (pool == null) ?
72e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            DefaultExecutorHolder.defaultExecutor : pool.executor();
73e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
74e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
75e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
76e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
77e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public void close() throws IOException {
78e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // mark channel as closed
79e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        synchronized (fdObj) {
80e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (closed)
81e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return;     // already closed
82e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            closed = true;
83e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            // from this point on, if another thread invokes the begin() method
84e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            // then it will throw ClosedChannelException
85e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
86e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
87e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // Invalidate and release any locks that we still hold
88e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        invalidateAllLocks();
89e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
90e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // signal any threads blocked on this channel
91e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        threads.signalAndWait();
92e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
93e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // wait until all async I/O operations have completely gracefully
94e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        closeLock.writeLock().lock();
95e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
96e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            // do nothing
97e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
98e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            closeLock.writeLock().unlock();
99e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
100e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
101e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // close file
102e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        nd.close(fdObj);
103e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
104e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
105e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
106e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public long size() throws IOException {
107e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        int ti = threads.add();
108e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
109e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            long n = 0L;
110e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            try {
111e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                begin();
112e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                do {
113e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    n = nd.size(fdObj);
114e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } while ((n == IOStatus.INTERRUPTED) && isOpen());
115e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return n;
116e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            } finally {
117e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                end(n >= 0L);
118e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
119e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
120e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            threads.remove(ti);
121e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
122e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
123e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
124e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
125e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public AsynchronousFileChannel truncate(long size) throws IOException {
126e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (size < 0L)
127e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new IllegalArgumentException("Negative size");
128e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!writing)
129e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonWritableChannelException();
130e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        int ti = threads.add();
131e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
132e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            long n = 0L;
133e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            try {
134e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                begin();
135e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                do {
136e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    n = nd.size(fdObj);
137e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } while ((n == IOStatus.INTERRUPTED) && isOpen());
138e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
139e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                // truncate file if 'size' less than current size
140e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                if (size < n && isOpen()) {
141e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    do {
142e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        n = nd.truncate(fdObj, size);
143e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
144e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
145e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return this;
146e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            } finally {
147e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                end(n > 0);
148e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
149e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
150e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            threads.remove(ti);
151e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
152e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
153e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
154e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
155e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public void force(boolean metaData) throws IOException {
156e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        int ti = threads.add();
157e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
158e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            int n = 0;
159e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            try {
160e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                begin();
161e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                do {
162e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    n = nd.force(fdObj, metaData);
163e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } while ((n == IOStatus.INTERRUPTED) && isOpen());
164e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            } finally {
165e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                end(n >= 0);
166e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
167e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
168e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            threads.remove(ti);
169e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
170e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
171e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
172e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
173e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    <A> Future<FileLock> implLock(final long position,
174e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final long size,
175e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final boolean shared,
176e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final A attachment,
177e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final CompletionHandler<FileLock,? super A> handler)
178e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
179e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (shared && !reading)
180e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonReadableChannelException();
181e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!shared && !writing)
182e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonWritableChannelException();
183e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
184e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // add to lock table
185e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        final FileLockImpl fli = addToFileLockTable(position, size, shared);
186e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (fli == null) {
187e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Throwable exc = new ClosedChannelException();
188e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (handler == null)
189e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return CompletedFuture.withFailure(exc);
190e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
191e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            return null;
192e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
193e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
194e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        final PendingFuture<FileLock,A> result = (handler == null) ?
195e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            new PendingFuture<FileLock,A>(this) : null;
196e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        Runnable task = new Runnable() {
197e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            public void run() {
198e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                Throwable exc = null;
199e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
200e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                int ti = threads.add();
201e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                try {
202e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    int n;
203e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    try {
204e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        begin();
205e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        do {
206e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                            n = nd.lock(fdObj, true, position, size, shared);
207e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
208e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        if (n != FileDispatcher.LOCKED || !isOpen()) {
209e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                            throw new AsynchronousCloseException();
210e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        }
211e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    } catch (IOException x) {
212e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        removeFromFileLockTable(fli);
213e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        if (!isOpen())
214e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                            x = new AsynchronousCloseException();
215e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        exc = x;
216e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    } finally {
217e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        end();
218e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    }
219e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } finally {
220e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    threads.remove(ti);
221e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
222e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                if (handler == null) {
223e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    result.setResult(fli, exc);
224e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } else {
225e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    Invoker.invokeUnchecked(handler, attachment, fli, exc);
226e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
227e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
228e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        };
229e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        boolean executed = false;
230e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
231e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            executor.execute(task);
232e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            executed = true;
233e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
234e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (!executed) {
235e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                // rollback
236e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                removeFromFileLockTable(fli);
237e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
238e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
239e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        return result;
240e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
241e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
242e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
243e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    public FileLock tryLock(long position, long size, boolean shared)
244e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        throws IOException
245e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
246e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (shared && !reading)
247e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonReadableChannelException();
248e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!shared && !writing)
249e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonWritableChannelException();
250e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
251e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // add to lock table
252e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        FileLockImpl fli = addToFileLockTable(position, size, shared);
253e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (fli == null)
254e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new ClosedChannelException();
255e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
256e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        int ti = threads.add();
257e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        boolean gotLock = false;
258e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        try {
259e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            begin();
260e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            int n;
261e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            do {
262e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                n = nd.lock(fdObj, false, position, size, shared);
263e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
264e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (n == FileDispatcher.LOCKED && isOpen()) {
265e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                gotLock = true;
266e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return fli;    // lock acquired
267e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
268e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (n == FileDispatcher.NO_LOCK)
269e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return null;    // locked by someone else
270e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (n == FileDispatcher.INTERRUPTED)
271e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                throw new AsynchronousCloseException();
272e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            // should not get here
273e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new AssertionError();
274e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        } finally {
275e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (!gotLock)
276e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                removeFromFileLockTable(fli);
277e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            end();
278e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            threads.remove(ti);
279e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
280e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
281e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
282e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
283e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    protected void implRelease(FileLockImpl fli) throws IOException {
284e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        nd.release(fdObj, fli.position(), fli.size());
285e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
286e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
287e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
288e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    <A> Future<Integer> implRead(final ByteBuffer dst,
289e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                 final long position,
290e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                 final A attachment,
291e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                 final CompletionHandler<Integer,? super A> handler)
292e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
293e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (position < 0)
294e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new IllegalArgumentException("Negative position");
295e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!reading)
296e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonReadableChannelException();
297e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (dst.isReadOnly())
298e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new IllegalArgumentException("Read-only buffer");
299e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
300e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // complete immediately if channel closed or no space remaining
301e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!isOpen() || (dst.remaining() == 0)) {
302e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Throwable exc = (isOpen()) ? null : new ClosedChannelException();
303e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (handler == null)
304e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return CompletedFuture.withResult(0, exc);
305e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
306e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            return null;
307e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
308e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
309e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        final PendingFuture<Integer,A> result = (handler == null) ?
310e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            new PendingFuture<Integer,A>(this) : null;
311e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        Runnable task = new Runnable() {
312e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            public void run() {
313e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                int n = 0;
314e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                Throwable exc = null;
315e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
316e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                int ti = threads.add();
317e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                try {
318e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    begin();
319e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    do {
320e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        n = IOUtil.read(fdObj, dst, position, nd);
321e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
322e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    if (n < 0 && !isOpen())
323e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        throw new AsynchronousCloseException();
324e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } catch (IOException x) {
325e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    if (!isOpen())
326e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        x = new AsynchronousCloseException();
327e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    exc = x;
328e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } finally {
329e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    end();
330e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    threads.remove(ti);
331e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
332e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                if (handler == null) {
333e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    result.setResult(n, exc);
334e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } else {
335e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    Invoker.invokeUnchecked(handler, attachment, n, exc);
336e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
337e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
338e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        };
339e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        executor.execute(task);
340e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        return result;
341e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
342e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
343e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    @Override
344e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    <A> Future<Integer> implWrite(final ByteBuffer src,
345e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final long position,
346e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final A attachment,
347e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                                  final CompletionHandler<Integer,? super A> handler)
348e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    {
349e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (position < 0)
350e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new IllegalArgumentException("Negative position");
351e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!writing)
352e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            throw new NonWritableChannelException();
353e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
354e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        // complete immediately if channel is closed or no bytes remaining
355e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        if (!isOpen() || (src.remaining() == 0)) {
356e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Throwable exc = (isOpen()) ? null : new ClosedChannelException();
357e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            if (handler == null)
358e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                return CompletedFuture.withResult(0, exc);
359e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
360e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            return null;
361e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        }
362e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
363e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        final PendingFuture<Integer,A> result = (handler == null) ?
364e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            new PendingFuture<Integer,A>(this) : null;
365e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        Runnable task = new Runnable() {
366e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            public void run() {
367e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                int n = 0;
368e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                Throwable exc = null;
369e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera
370e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                int ti = threads.add();
371e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                try {
372e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    begin();
373e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    do {
374e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        n = IOUtil.write(fdObj, src, position, nd);
375e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    } while ((n == IOStatus.INTERRUPTED) && isOpen());
376e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    if (n < 0 && !isOpen())
377e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        throw new AsynchronousCloseException();
378e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } catch (IOException x) {
379e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    if (!isOpen())
380e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                        x = new AsynchronousCloseException();
381e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    exc = x;
382e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } finally {
383e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    end();
384e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    threads.remove(ti);
385e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
386e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                if (handler == null) {
387e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    result.setResult(n, exc);
388e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                } else {
389e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                    Invoker.invokeUnchecked(handler, attachment, n, exc);
390e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera                }
391e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera            }
392e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        };
393e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        executor.execute(task);
394e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera        return result;
395e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera    }
396e6bac4bf9c85c2454ce22c91da6c654552c268e0Shubham Ajmera}
397