提交 6277f7b6 编写于 作者: A asaha

Merge

...@@ -196,10 +196,12 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private ...@@ -196,10 +196,12 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
if ((start < 0) || (end > len) || (start > end)) if ((start < 0) || (end > len) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int sublen = end - start; return new ByteBufferAsCharBuffer$RW$$BO$(bb,
int off = offset + ((pos + start) << $LG_BYTES_PER_VALUE$); -1,
assert (off >= 0); pos + start,
return new ByteBufferAsCharBuffer$RW$$BO$(bb, -1, 0, sublen, sublen, off); pos + end,
capacity(),
offset);
} }
#end[char] #end[char]
......
...@@ -412,10 +412,12 @@ class Direct$Type$Buffer$RW$$BO$ ...@@ -412,10 +412,12 @@ class Direct$Type$Buffer$RW$$BO$
if ((start < 0) || (end > len) || (start > end)) if ((start < 0) || (end > len) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int sublen = end - start; return new DirectCharBuffer$RW$$BO$(this,
int off = (pos + start) << $LG_BYTES_PER_VALUE$; -1,
assert (off >= 0); pos + start,
return new DirectCharBuffer$RW$$BO$(this, -1, 0, sublen, sublen, off); pos + end,
capacity(),
offset);
} }
#end[char] #end[char]
......
...@@ -572,10 +572,13 @@ class Heap$Type$Buffer$RW$ ...@@ -572,10 +572,13 @@ class Heap$Type$Buffer$RW$
|| (end > length()) || (end > length())
|| (start > end)) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int len = end - start; int pos = position();
return new HeapCharBuffer$RW$(hb, return new HeapCharBuffer$RW$(hb,
-1, 0, len, len, -1,
offset + position() + start); pos + start,
pos + end,
capacity(),
offset);
} }
#end[char] #end[char]
......
...@@ -102,10 +102,12 @@ class StringCharBuffer // package-private ...@@ -102,10 +102,12 @@ class StringCharBuffer // package-private
public final CharBuffer subSequence(int start, int end) { public final CharBuffer subSequence(int start, int end) {
try { try {
int pos = position(); int pos = position();
return new StringCharBuffer(str, -1, return new StringCharBuffer(str,
-1,
pos + checkIndex(start, pos), pos + checkIndex(start, pos),
pos + checkIndex(end, pos), pos + checkIndex(end, pos),
remaining(), offset); capacity(),
offset);
} catch (IllegalArgumentException x) { } catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
......
...@@ -113,16 +113,16 @@ abstract class AsynchronousFileChannelImpl ...@@ -113,16 +113,16 @@ abstract class AsynchronousFileChannelImpl
} }
} }
final void invalidateAllLocks() { final void invalidateAllLocks() throws IOException {
if (fileLockTable != null) { if (fileLockTable != null) {
try { for (FileLock fl: fileLockTable.removeAll()) {
fileLockTable.removeAll( new FileLockTable.Releaser() { synchronized (fl) {
public void release(FileLock fl) { if (fl.isValid()) {
((FileLockImpl)fl).invalidate(); FileLockImpl fli = (FileLockImpl)fl;
implRelease(fli);
fli.invalidate();
} }
}); }
} catch (IOException e) {
throw new AssertionError(e);
} }
} }
} }
...@@ -158,7 +158,21 @@ abstract class AsynchronousFileChannelImpl ...@@ -158,7 +158,21 @@ abstract class AsynchronousFileChannelImpl
} }
/** /**
* Invoked by FileLockImpl to release lock acquired by this channel. * Releases the given file lock.
*/
protected abstract void implRelease(FileLockImpl fli) throws IOException;
/**
* Invoked by FileLockImpl to release the given file lock and remove it
* from the lock table.
*/ */
abstract void release(FileLockImpl fli) throws IOException; final void release(FileLockImpl fli) throws IOException {
try {
begin();
implRelease(fli);
removeFromFileLockTable(fli);
} finally {
end();
}
}
} }
...@@ -33,8 +33,6 @@ import java.nio.BufferPoolMXBean; ...@@ -33,8 +33,6 @@ import java.nio.BufferPoolMXBean;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Iterator;
import java.lang.reflect.Field;
import java.security.AccessController; import java.security.AccessController;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
...@@ -95,14 +93,16 @@ public class FileChannelImpl ...@@ -95,14 +93,16 @@ public class FileChannelImpl
// -- Standard channel operations -- // -- Standard channel operations --
protected void implCloseChannel() throws IOException { protected void implCloseChannel() throws IOException {
// Invalidate and release any locks that we still hold // Release and invalidate any locks that we still hold
if (fileLockTable != null) { if (fileLockTable != null) {
fileLockTable.removeAll( new FileLockTable.Releaser() { for (FileLock fl: fileLockTable.removeAll()) {
public void release(FileLock fl) throws IOException { synchronized (fl) {
((FileLockImpl)fl).invalidate(); if (fl.isValid()) {
nd.release(fd, fl.position(), fl.size()); nd.release(fd, fl.position(), fl.size());
((FileLockImpl)fl).invalidate();
}
} }
}); }
} }
nd.preClose(fd); nd.preClose(fd);
...@@ -912,32 +912,33 @@ public class FileChannelImpl ...@@ -912,32 +912,33 @@ public class FileChannelImpl
FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable(); FileLockTable flt = fileLockTable();
flt.add(fli); flt.add(fli);
boolean i = true; boolean completed = false;
int ti = -1; int ti = -1;
try { try {
begin(); begin();
ti = threads.add(); ti = threads.add();
if (!isOpen()) if (!isOpen())
return null; return null;
int result = nd.lock(fd, true, position, size, shared); int n;
if (result == FileDispatcher.RET_EX_LOCK) { do {
assert shared; n = nd.lock(fd, true, position, size, shared);
FileLockImpl fli2 = new FileLockImpl(this, position, size, } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
false); if (isOpen()) {
flt.replace(fli, fli2); if (n == FileDispatcher.RET_EX_LOCK) {
return fli2; assert shared;
} FileLockImpl fli2 = new FileLockImpl(this, position, size,
if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) { false);
flt.remove(fli); flt.replace(fli, fli2);
i = false; fli = fli2;
}
completed = true;
} }
} catch (IOException e) {
flt.remove(fli);
throw e;
} finally { } finally {
if (!completed)
flt.remove(fli);
threads.remove(ti); threads.remove(ti);
try { try {
end(i); end(completed);
} catch (ClosedByInterruptException e) { } catch (ClosedByInterruptException e) {
throw new FileLockInterruptionException(); throw new FileLockInterruptionException();
} }
...@@ -985,7 +986,6 @@ public class FileChannelImpl ...@@ -985,7 +986,6 @@ public class FileChannelImpl
} }
void release(FileLockImpl fli) throws IOException { void release(FileLockImpl fli) throws IOException {
ensureOpen();
int ti = threads.add(); int ti = threads.add();
try { try {
ensureOpen(); ensureOpen();
...@@ -1005,7 +1005,7 @@ public class FileChannelImpl ...@@ -1005,7 +1005,7 @@ public class FileChannelImpl
*/ */
private static class SimpleFileLockTable extends FileLockTable { private static class SimpleFileLockTable extends FileLockTable {
// synchronize on list for access // synchronize on list for access
private List<FileLock> lockList = new ArrayList<FileLock>(2); private final List<FileLock> lockList = new ArrayList<FileLock>(2);
public SimpleFileLockTable() { public SimpleFileLockTable() {
} }
...@@ -1034,14 +1034,11 @@ public class FileChannelImpl ...@@ -1034,14 +1034,11 @@ public class FileChannelImpl
} }
} }
public void removeAll(Releaser releaser) throws IOException { public List<FileLock> removeAll() {
synchronized(lockList) { synchronized(lockList) {
Iterator<FileLock> i = lockList.iterator(); List<FileLock> result = new ArrayList<FileLock>(lockList);
while (i.hasNext()) { lockList.clear();
FileLock fl = i.next(); return result;
releaser.release(fl);
i.remove();
}
} }
} }
......
...@@ -31,25 +31,24 @@ import java.nio.channels.*; ...@@ -31,25 +31,24 @@ import java.nio.channels.*;
public class FileLockImpl public class FileLockImpl
extends FileLock extends FileLock
{ {
boolean valid; private volatile boolean valid = true;
FileLockImpl(FileChannel channel, long position, long size, boolean shared) FileLockImpl(FileChannel channel, long position, long size, boolean shared)
{ {
super(channel, position, size, shared); super(channel, position, size, shared);
this.valid = true;
} }
FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared) FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared)
{ {
super(channel, position, size, shared); super(channel, position, size, shared);
this.valid = true;
} }
public synchronized boolean isValid() { public boolean isValid() {
return valid; return valid;
} }
synchronized void invalidate() { void invalidate() {
assert Thread.holdsLock(this);
valid = false; valid = false;
} }
...@@ -66,5 +65,4 @@ public class FileLockImpl ...@@ -66,5 +65,4 @@ public class FileLockImpl
valid = false; valid = false;
} }
} }
} }
...@@ -60,23 +60,12 @@ abstract class FileLockTable { ...@@ -60,23 +60,12 @@ abstract class FileLockTable {
*/ */
public abstract void remove(FileLock fl); public abstract void remove(FileLock fl);
/**
* An implementation of this interface releases a given file lock.
* Used with removeAll.
*/
public abstract interface Releaser {
void release(FileLock fl) throws IOException;
}
/** /**
* Removes all file locks from the table. * Removes all file locks from the table.
* <p>
* The Releaser#release method is invoked for each file lock before
* it is removed.
* *
* @throws IOException if the release method throws IOException * @return The list of file locks removed
*/ */
public abstract void removeAll(Releaser r) throws IOException; public abstract List<FileLock> removeAll();
/** /**
* Replaces an existing file lock in the table. * Replaces an existing file lock in the table.
...@@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable { ...@@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable {
FileLockReference ref = list.get(index); FileLockReference ref = list.get(index);
FileLock lock = ref.get(); FileLock lock = ref.get();
if (lock == fl) { if (lock == fl) {
assert (lock != null) && (lock.channel() == channel); assert (lock != null) && (lock.acquiredBy() == channel);
ref.clear(); ref.clear();
list.remove(index); list.remove(index);
break; break;
...@@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable { ...@@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable {
} }
@Override @Override
public void removeAll(Releaser releaser) throws IOException { public List<FileLock> removeAll() {
List<FileLock> result = new ArrayList<FileLock>();
List<FileLockReference> list = lockMap.get(fileKey); List<FileLockReference> list = lockMap.get(fileKey);
if (list != null) { if (list != null) {
synchronized (list) { synchronized (list) {
...@@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable { ...@@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable {
FileLock lock = ref.get(); FileLock lock = ref.get();
// remove locks obtained by this channel // remove locks obtained by this channel
if (lock != null && lock.channel() == channel) { if (lock != null && lock.acquiredBy() == channel) {
// invoke the releaser to invalidate/release the lock
releaser.release(lock);
// remove the lock from the list // remove the lock from the list
ref.clear(); ref.clear();
list.remove(index); list.remove(index);
// add to result
result.add(lock);
} else { } else {
index++; index++;
} }
...@@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable { ...@@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable {
removeKeyIfEmpty(fileKey, list); removeKeyIfEmpty(fileKey, list);
} }
} }
return result;
} }
@Override @Override
......
...@@ -97,6 +97,9 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -97,6 +97,9 @@ public class SimpleAsynchronousFileChannelImpl
// then it will throw ClosedChannelException // then it will throw ClosedChannelException
} }
// Invalidate and release any locks that we still hold
invalidateAllLocks();
// signal any threads blocked on this channel // signal any threads blocked on this channel
nd.preClose(fdObj); nd.preClose(fdObj);
threads.signalAndWait(); threads.signalAndWait();
...@@ -109,9 +112,6 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -109,9 +112,6 @@ public class SimpleAsynchronousFileChannelImpl
closeLock.writeLock().unlock(); closeLock.writeLock().unlock();
} }
// Invalidate and release any locks that we still hold
invalidateAllLocks();
// close file // close file
nd.close(fdObj); nd.close(fdObj);
...@@ -226,11 +226,9 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -226,11 +226,9 @@ public class SimpleAsynchronousFileChannelImpl
do { do {
n = nd.lock(fdObj, true, position, size, shared); n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen()); } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n == FileDispatcher.LOCKED) { if (n == FileDispatcher.LOCKED && isOpen()) {
result.setResult(fli); result.setResult(fli);
} else { } else {
if (n != FileDispatcher.INTERRUPTED)
throw new AssertionError();
throw new AsynchronousCloseException(); throw new AsynchronousCloseException();
} }
} catch (IOException x) { } catch (IOException x) {
...@@ -279,16 +277,16 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -279,16 +277,16 @@ public class SimpleAsynchronousFileChannelImpl
do { do {
n = nd.lock(fdObj, false, position, size, shared); n = nd.lock(fdObj, false, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen()); } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n != FileDispatcher.LOCKED) { if (n == FileDispatcher.LOCKED && isOpen()) {
if (n == FileDispatcher.NO_LOCK) gotLock = true;
return null; // locked by someone else return fli; // lock acquired
if (n == FileDispatcher.INTERRUPTED)
throw new AsynchronousCloseException();
// should not get here
throw new AssertionError();
} }
gotLock = true; if (n == FileDispatcher.NO_LOCK)
return fli; return null; // locked by someone else
if (n == FileDispatcher.INTERRUPTED)
throw new AsynchronousCloseException();
// should not get here
throw new AssertionError();
} finally { } finally {
if (!gotLock) if (!gotLock)
removeFromFileLockTable(fli); removeFromFileLockTable(fli);
...@@ -298,14 +296,8 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -298,14 +296,8 @@ public class SimpleAsynchronousFileChannelImpl
} }
@Override @Override
void release(FileLockImpl fli) throws IOException { protected void implRelease(FileLockImpl fli) throws IOException {
try { nd.release(fdObj, fli.position(), fli.size());
begin();
nd.release(fdObj, fli.position(), fli.size());
removeFromFileLockTable(fli);
} finally {
end();
}
} }
@Override @Override
......
...@@ -354,16 +354,9 @@ public class WindowsAsynchronousFileChannelImpl ...@@ -354,16 +354,9 @@ public class WindowsAsynchronousFileChannelImpl
} }
} }
// invoke by FileFileImpl to release lock
@Override @Override
void release(FileLockImpl fli) throws IOException { protected void implRelease(FileLockImpl fli) throws IOException {
try { nd.release(fdObj, fli.position(), fli.size());
begin();
nd.release(fdObj, fli.position(), fli.size());
removeFromFileLockTable(fli);
} finally {
end();
}
} }
/** /**
......
...@@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, ...@@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
o.Offset = lowPos; o.Offset = lowPos;
o.OffsetHigh = highPos; o.OffsetHigh = highPos;
result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
if (result == 0) { if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) {
JNU_ThrowIOExceptionWithLastError(env, "Release failed"); JNU_ThrowIOExceptionWithLastError(env, "Release failed");
} }
} }
......
...@@ -365,8 +365,11 @@ public class Basic$Type$ ...@@ -365,8 +365,11 @@ public class Basic$Type$
b.position(2); b.position(2);
ck(b, b.charAt(1), 'd'); ck(b, b.charAt(1), 'd');
CharBuffer c = (CharBuffer)b.subSequence(1, 4); CharBuffer c = b.subSequence(1, 4);
ck(b, b.subSequence(1, 4).toString().equals("def")); ck(c, c.capacity(), b.capacity());
ck(c, c.position(), b.position()+1);
ck(c, c.limit(), b.position()+4);
ck(c, b.subSequence(1, 4).toString().equals("def"));
// 4938424 // 4938424
b.position(4); b.position(4);
...@@ -722,6 +725,8 @@ public class Basic$Type$ ...@@ -722,6 +725,8 @@ public class Basic$Type$
ck(b, start, b.position()); ck(b, start, b.position());
ck(b, end, b.limit()); ck(b, end, b.limit());
ck(b, s.length(), b.capacity()); ck(b, s.length(), b.capacity());
b.position(6);
ck(b, b.subSequence(0,3).toString().equals("ghi"));
// The index, relative to the position, must be non-negative and // The index, relative to the position, must be non-negative and
// smaller than remaining(). // smaller than remaining().
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* @summary Unit test for buffers * @summary Unit test for buffers
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725 * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529 * 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
* 6221101 6234263 6535542 6591971 6593946 * 6221101 6234263 6535542 6591971 6593946 6795561
* @author Mark Reinhold * @author Mark Reinhold
*/ */
......
...@@ -371,6 +371,9 @@ public class BasicByte ...@@ -371,6 +371,9 @@ public class BasicByte
...@@ -783,6 +786,8 @@ public class BasicByte ...@@ -783,6 +786,8 @@ public class BasicByte
......
...@@ -365,8 +365,11 @@ public class BasicChar ...@@ -365,8 +365,11 @@ public class BasicChar
b.position(2); b.position(2);
ck(b, b.charAt(1), 'd'); ck(b, b.charAt(1), 'd');
CharBuffer c = (CharBuffer)b.subSequence(1, 4); CharBuffer c = b.subSequence(1, 4);
ck(b, b.subSequence(1, 4).toString().equals("def")); ck(c, c.capacity(), b.capacity());
ck(c, c.position(), b.position()+1);
ck(c, c.limit(), b.position()+4);
ck(c, b.subSequence(1, 4).toString().equals("def"));
// 4938424 // 4938424
b.position(4); b.position(4);
...@@ -722,6 +725,8 @@ public class BasicChar ...@@ -722,6 +725,8 @@ public class BasicChar
ck(b, start, b.position()); ck(b, start, b.position());
ck(b, end, b.limit()); ck(b, end, b.limit());
ck(b, s.length(), b.capacity()); ck(b, s.length(), b.capacity());
b.position(6);
ck(b, b.subSequence(0,3).toString().equals("ghi"));
// The index, relative to the position, must be non-negative and // The index, relative to the position, must be non-negative and
// smaller than remaining(). // smaller than remaining().
......
...@@ -371,6 +371,9 @@ public class BasicDouble ...@@ -371,6 +371,9 @@ public class BasicDouble
...@@ -783,6 +786,8 @@ public class BasicDouble ...@@ -783,6 +786,8 @@ public class BasicDouble
......
...@@ -371,6 +371,9 @@ public class BasicFloat ...@@ -371,6 +371,9 @@ public class BasicFloat
...@@ -783,6 +786,8 @@ public class BasicFloat ...@@ -783,6 +786,8 @@ public class BasicFloat
......
...@@ -371,6 +371,9 @@ public class BasicInt ...@@ -371,6 +371,9 @@ public class BasicInt
...@@ -783,6 +786,8 @@ public class BasicInt ...@@ -783,6 +786,8 @@ public class BasicInt
......
...@@ -371,6 +371,9 @@ public class BasicLong ...@@ -371,6 +371,9 @@ public class BasicLong
...@@ -783,6 +786,8 @@ public class BasicLong ...@@ -783,6 +786,8 @@ public class BasicLong
......
...@@ -371,6 +371,9 @@ public class BasicShort ...@@ -371,6 +371,9 @@ public class BasicShort
...@@ -783,6 +786,8 @@ public class BasicShort ...@@ -783,6 +786,8 @@ public class BasicShort
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4607272 * @bug 4607272 6822643
* @summary Unit test for AsynchronousFileChannel * @summary Unit test for AsynchronousFileChannel
*/ */
...@@ -51,7 +51,6 @@ public class Basic { ...@@ -51,7 +51,6 @@ public class Basic {
// run tests // run tests
testUsingCompletionHandlers(ch); testUsingCompletionHandlers(ch);
testUsingWaitOnResult(ch); testUsingWaitOnResult(ch);
testLocking(ch);
testInterruptHandlerThread(ch); testInterruptHandlerThread(ch);
// close channel and invoke test that expects channel to be closed // close channel and invoke test that expects channel to be closed
...@@ -59,6 +58,7 @@ public class Basic { ...@@ -59,6 +58,7 @@ public class Basic {
testClosedChannel(ch); testClosedChannel(ch);
// these tests open the file themselves // these tests open the file themselves
testLocking(blah.toPath());
testCustomThreadPool(blah.toPath()); testCustomThreadPool(blah.toPath());
testAsynchronousClose(blah.toPath()); testAsynchronousClose(blah.toPath());
testCancel(blah.toPath()); testCancel(blah.toPath());
...@@ -160,47 +160,54 @@ public class Basic { ...@@ -160,47 +160,54 @@ public class Basic {
} }
// exercise lock methods // exercise lock methods
static void testLocking(AsynchronousFileChannel ch) static void testLocking(Path file) throws IOException {
throws IOException
{
System.out.println("testLocking"); System.out.println("testLocking");
// test 1 - acquire lock and check that tryLock throws AsynchronousFileChannel ch = AsynchronousFileChannel
// OverlappingFileLockException .open(file, READ, WRITE);
FileLock fl; FileLock fl;
try { try {
fl = ch.lock().get(); // test 1 - acquire lock and check that tryLock throws
} catch (ExecutionException x) { // OverlappingFileLockException
throw new RuntimeException(x); try {
} catch (InterruptedException x) { fl = ch.lock().get();
throw new RuntimeException("Should not be interrupted"); } catch (ExecutionException x) {
} throw new RuntimeException(x);
if (!fl.acquiredBy().equals(ch)) } catch (InterruptedException x) {
throw new RuntimeException("FileLock#acquiredBy returned incorrect channel"); throw new RuntimeException("Should not be interrupted");
try { }
ch.tryLock(); if (!fl.acquiredBy().equals(ch))
throw new RuntimeException("OverlappingFileLockException expected"); throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
} catch (OverlappingFileLockException x) { try {
} ch.tryLock();
fl.release(); throw new RuntimeException("OverlappingFileLockException expected");
} catch (OverlappingFileLockException x) {
}
fl.release();
// test 2 - acquire try and check that lock throws OverlappingFileLockException // test 2 - acquire try and check that lock throws OverlappingFileLockException
fl = ch.tryLock(); fl = ch.tryLock();
if (fl == null) if (fl == null)
throw new RuntimeException("Unable to acquire lock"); throw new RuntimeException("Unable to acquire lock");
try { try {
ch.lock(null, new CompletionHandler<FileLock,Void> () { ch.lock(null, new CompletionHandler<FileLock,Void> () {
public void completed(FileLock result, Void att) { public void completed(FileLock result, Void att) {
} }
public void failed(Throwable exc, Void att) { public void failed(Throwable exc, Void att) {
} }
public void cancelled(Void att) { public void cancelled(Void att) {
} }
}); });
throw new RuntimeException("OverlappingFileLockException expected"); throw new RuntimeException("OverlappingFileLockException expected");
} catch (OverlappingFileLockException x) { } catch (OverlappingFileLockException x) {
}
} finally {
ch.close();
} }
fl.release();
// test 3 - channel is closed so FileLock should no longer be valid
if (fl.isValid())
throw new RuntimeException("FileLock expected to be invalid");
} }
// interrupt should not close channel // interrupt should not close channel
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* @test /* @test
* @bug 4607272 * @bug 4607272 6814948
* @summary Unit test for AsynchronousFileChannel#lock method * @summary Unit test for AsynchronousFileChannel#lock method
*/ */
......
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* @test
* @bug 6543863
* @summary Try to cause a deadlock between (Asynchronous)FileChannel.close
* and FileLock.release
*/
import java.io.*;
import java.nio.file.Path;
import static java.nio.file.StandardOpenOption.*;
import java.nio.channels.*;
import java.util.concurrent.*;
public class ReleaseOnCloseDeadlock {
private static final int LOCK_COUNT = 1024;
public static void main(String[] args) throws IOException {
File blah = File.createTempFile("blah", null);
blah.deleteOnExit();
for (int i=0; i<100; i++) {
test(blah.toPath());
}
}
static void test(Path file) throws IOException {
FileLock[] locks = new FileLock[LOCK_COUNT];
FileChannel fc = FileChannel.open(file, READ, WRITE);
for (int i=0; i<LOCK_COUNT; i++) {
locks[i] = fc.lock(i, 1, true);
}
tryToDeadlock(fc, locks);
AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE);
for (int i=0; i<LOCK_COUNT; i++) {
try {
locks[i] = ch.lock(i, 1, true, null, null).get();
} catch (InterruptedException x) {
throw new RuntimeException(x);
} catch (ExecutionException x) {
throw new RuntimeException(x);
}
}
tryToDeadlock(ch, locks);
}
static void tryToDeadlock(final Channel channel, FileLock[] locks)
throws IOException
{
// start thread to close the file (and invalidate the locks)
Thread closer = new Thread(
new Runnable() {
public void run() {
try {
channel.close();
} catch (IOException ignore) {
ignore.printStackTrace();
}
}});
closer.start();
// release the locks explicitly
for (int i=0; i<locks.length; i++) {
try {
locks[i].release();
} catch (ClosedChannelException ignore) { }
}
// we are done when closer has terminated
while (closer.isAlive()) {
try {
closer.join();
} catch (InterruptedException ignore) { }
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册