提交 079c91bf authored 作者: Noel Grandin's avatar Noel Grandin

fix concurrency issues in compressed FilePathNioMem

unfortunately I had to hit it with the big synchronization stick. I
could no simple way to rescue the current rather clever code.

This bug was reported by Anatolii K  in this message:
https://groups.google.com/d/msg/h2-database/rhSoRhzeZzk/gc-pNlSpEwAJ
上级 333a5027
...@@ -399,11 +399,13 @@ class FileNioMemData { ...@@ -399,11 +399,13 @@ class FileNioMemData {
private static final int BLOCK_SIZE = 1 << BLOCK_SIZE_SHIFT; private static final int BLOCK_SIZE = 1 << BLOCK_SIZE_SHIFT;
private static final int BLOCK_SIZE_MASK = BLOCK_SIZE - 1; private static final int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
private static final CompressLZF LZF = new CompressLZF();
private static final byte[] BUFFER = new byte[BLOCK_SIZE * 2];
private static final ByteBuffer COMPRESSED_EMPTY_BLOCK; private static final ByteBuffer COMPRESSED_EMPTY_BLOCK;
private static final CompressLaterCache<CompressItem, CompressItem> COMPRESS_LATER = private final CompressLZF LZF = new CompressLZF();
/** the output buffer when compressing */
private final byte[] compressOutputBuffer = new byte[BLOCK_SIZE * 2];
private final CompressLaterCache<CompressItem, CompressItem> compressLaterCache =
new CompressLaterCache<CompressItem, CompressItem>(CACHE_SIZE); new CompressLaterCache<CompressItem, CompressItem>(CACHE_SIZE);
private String name; private String name;
...@@ -417,10 +419,11 @@ class FileNioMemData { ...@@ -417,10 +419,11 @@ class FileNioMemData {
private int sharedLockCount; private int sharedLockCount;
static { static {
byte[] n = new byte[BLOCK_SIZE]; final byte[] n = new byte[BLOCK_SIZE];
int len = LZF.compress(n, BLOCK_SIZE, BUFFER, 0); final byte[] output = new byte[BLOCK_SIZE * 2];
int len = new CompressLZF().compress(n, BLOCK_SIZE, output, 0);
COMPRESSED_EMPTY_BLOCK = ByteBuffer.allocateDirect(len); COMPRESSED_EMPTY_BLOCK = ByteBuffer.allocateDirect(len);
COMPRESSED_EMPTY_BLOCK.put(BUFFER, 0, len); COMPRESSED_EMPTY_BLOCK.put(output, 0, len);
} }
FileNioMemData(String name, boolean compress) { FileNioMemData(String name, boolean compress) {
...@@ -530,9 +533,7 @@ class FileNioMemData { ...@@ -530,9 +533,7 @@ class FileNioMemData {
private void addToCompressLaterCache(int page) { private void addToCompressLaterCache(int page) {
CompressItem c = new CompressItem(this, page); CompressItem c = new CompressItem(this, page);
synchronized (LZF) { compressLaterCache.put(c, c);
COMPRESS_LATER.put(c, c);
}
} }
private void expand(int page) { private void expand(int page) {
...@@ -548,11 +549,9 @@ class FileNioMemData { ...@@ -548,11 +549,9 @@ class FileNioMemData {
} }
ByteBuffer out = ByteBuffer.allocateDirect(BLOCK_SIZE); ByteBuffer out = ByteBuffer.allocateDirect(BLOCK_SIZE);
if (d != COMPRESSED_EMPTY_BLOCK) { if (d != COMPRESSED_EMPTY_BLOCK) {
synchronized (LZF) {
d.position(0); d.position(0);
CompressLZF.expand(d, out); CompressLZF.expand(d, out);
} }
}
list[page] = out; list[page] = out;
} }
...@@ -568,13 +567,11 @@ class FileNioMemData { ...@@ -568,13 +567,11 @@ class FileNioMemData {
return; return;
} }
ByteBuffer d = list[page]; ByteBuffer d = list[page];
synchronized (LZF) { int len = LZF.compress(d, 0, compressOutputBuffer, 0);
int len = LZF.compress(d, 0, BUFFER, 0);
d = ByteBuffer.allocateDirect(len); d = ByteBuffer.allocateDirect(len);
d.put(BUFFER, 0, len); d.put(compressOutputBuffer, 0, len);
list[page] = d; list[page] = d;
} }
}
/** /**
* Update the last modified time. * Update the last modified time.
...@@ -602,7 +599,7 @@ class FileNioMemData { ...@@ -602,7 +599,7 @@ class FileNioMemData {
* *
* @param newLength the new length * @param newLength the new length
*/ */
void truncate(long newLength) { synchronized void truncate(long newLength) {
changeLength(newLength); changeLength(newLength);
long end = MathUtils.roundUpLong(newLength, BLOCK_SIZE); long end = MathUtils.roundUpLong(newLength, BLOCK_SIZE);
if (end != newLength) { if (end != newLength) {
...@@ -642,7 +639,7 @@ class FileNioMemData { ...@@ -642,7 +639,7 @@ class FileNioMemData {
* @param write true for writing * @param write true for writing
* @return the new position * @return the new position
*/ */
long readWrite(long pos, ByteBuffer b, int off, int len, boolean write) { synchronized long readWrite(long pos, ByteBuffer b, int off, int len, boolean write) {
long end = pos + len; long end = pos + len;
if (end > length) { if (end > length) {
if (write) { if (write) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论