Merge
This commit is contained in:
commit
d3af1f284c
@ -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$
|
|||||||
|
|
||||||
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$
|
|||||||
|| (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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked by FileLockImpl to release lock acquired by this channel.
|
* Releases the given file lock.
|
||||||
*/
|
*/
|
||||||
abstract void release(FileLockImpl fli) throws IOException;
|
protected abstract void implRelease(FileLockImpl fli) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked by FileLockImpl to release the given file lock and remove it
|
||||||
|
* from the lock table.
|
||||||
|
*/
|
||||||
|
final void release(FileLockImpl fli) throws IOException {
|
||||||
|
try {
|
||||||
|
begin();
|
||||||
|
implRelease(fli);
|
||||||
|
removeFromFileLockTable(fli);
|
||||||
|
} finally {
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|||||||
// -- 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
|
|||||||
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,
|
||||||
|
false);
|
||||||
|
flt.replace(fli, fli2);
|
||||||
|
fli = fli2;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
}
|
}
|
||||||
if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) {
|
|
||||||
flt.remove(fli);
|
|
||||||
i = false;
|
|
||||||
}
|
|
||||||
} 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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
*/
|
*/
|
||||||
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.*;
|
|||||||
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
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
|||||||
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 {
|
|||||||
removeKeyIfEmpty(fileKey, list);
|
removeKeyIfEmpty(fileKey, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -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
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
@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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
|||||||
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$
|
|||||||
|
|
||||||
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$
|
|||||||
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 @@
|
|||||||
* @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
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicByte
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
|||||||
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
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicDouble
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,6 +371,9 @@ public class BasicFloat
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicFloat
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,6 +371,9 @@ public class BasicInt
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicInt
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,6 +371,9 @@ public class BasicLong
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicLong
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,6 +371,9 @@ public class BasicShort
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -783,6 +786,8 @@ public class BasicShort
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 {
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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 @@
|
|||||||
|
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4607272
|
* @bug 4607272 6814948
|
||||||
* @summary Unit test for AsynchronousFileChannel#lock method
|
* @summary Unit test for AsynchronousFileChannel#lock method
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user