avoid accessing invalid buffer

This commit is contained in:
Maxim.Mossienko
2014-07-14 13:10:29 +02:00
parent 159f3c5145
commit 0896a251b1
3 changed files with 27 additions and 17 deletions
@@ -158,7 +158,7 @@ public class AppendableStorageBackedByResizableMappedFile extends ResizeableMapp
int base = addr;
int address = storage.getOffsetInPage(addr);
boolean same = true;
ByteBuffer buffer = storage.getByteBuffer(addr, false);
ByteBuffer buffer = storage.getByteBuffer(addr, false).getCachedBuffer();
final int myPageSize = storage.myPageSize;
@Override
@@ -166,7 +166,7 @@ public class AppendableStorageBackedByResizableMappedFile extends ResizeableMapp
if (same) {
if (myPageSize == address && address < myFileLength) { // reached end of current byte buffer
base += address;
buffer = storage.getByteBuffer(base, false);
buffer = storage.getByteBuffer(base, false).getCachedBuffer();
address = 0;
}
same = address < myFileLength && buffer.get(address++) == (byte)b;
@@ -203,7 +203,7 @@ class IntToIntBtree {
boolean canUseLastKey = myCanUseLastKey;
if (canUseLastKey) {
myCanUseLastKey = false;
if (key == myLastGetKey && !myAccessNodeView.myHasFullPagesAlongPath) {
if (key == myLastGetKey && !myAccessNodeView.myHasFullPagesAlongPath && myAccessNodeView.isValid()) {
++myOptimizedInserts;
++count;
myAccessNodeView.insert(key, value);
@@ -284,6 +284,7 @@ class IntToIntBtree {
private short myChildrenCount;
protected int myAddressInBuffer;
protected ByteBuffer myBuffer;
protected ByteBufferWrapper myBufferWrapper;
protected boolean myHasFullPagesAlongPath;
protected boolean myIsDirty;
@@ -302,7 +303,8 @@ class IntToIntBtree {
protected void syncWithStore() {
PagedFileStorage pagedFileStorage = btree.storage.getPagedFileStorage();
myAddressInBuffer = pagedFileStorage.getOffsetInPage(address);
myBuffer = pagedFileStorage.getByteBuffer(address, false);
myBufferWrapper = pagedFileStorage.getByteBuffer(address, false);
myBuffer = myBufferWrapper.getCachedBuffer();
myIsDirty = false; // we will mark dirty on child count change, attrs change or existing key put
doInitFlags(myBuffer.getInt(myAddressInBuffer));
}
@@ -541,6 +543,10 @@ class IntToIntBtree {
setAddress(address);
}
public boolean isValid() {
return myBufferWrapper.getCachedBuffer() == myBuffer;
}
private static class HashLeafData {
final BtreeIndexNodeView nodeView;
final int[] keys;
@@ -151,7 +151,7 @@ public class PagedFileStorage implements Forceable {
if (myValuesAreBufferAligned) {
long page = addr / myPageSize;
int page_offset = (int) (addr % myPageSize);
return getBuffer(page, false).getInt(page_offset);
return getReadOnlyBuffer(page).getInt(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 4);
return Bits.getInt(myTypedIOBuffer, 0);
@@ -173,15 +173,15 @@ public class PagedFileStorage implements Forceable {
return (int)(addr % myPageSize);
}
ByteBuffer getByteBuffer(long address, boolean modify) {
return getBuffer(address / myPageSize, modify);
ByteBufferWrapper getByteBuffer(long address, boolean modify) {
return getBufferWrapper(address / myPageSize, modify);
}
public final short getShort(long addr) {
if (myValuesAreBufferAligned) {
long page = addr / myPageSize;
int page_offset = (int)(addr % myPageSize);
return getBuffer(page, false).getShort(page_offset);
return getReadOnlyBuffer(page).getShort(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 2);
return Bits.getShort(myTypedIOBuffer, 0);
@@ -212,7 +212,7 @@ public class PagedFileStorage implements Forceable {
if (myValuesAreBufferAligned) {
long page = addr / myPageSize;
int page_offset = (int)(addr % myPageSize);
return getBuffer(page, false).getLong(page_offset);
return getReadOnlyBuffer(page).getLong(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 8);
return Bits.getLong(myTypedIOBuffer, 0);
@@ -223,7 +223,7 @@ public class PagedFileStorage implements Forceable {
long page = index / myPageSize;
int offset = (int)(index % myPageSize);
return getBuffer(page, false).get(offset);
return getReadOnlyBuffer(page).get(offset);
}
public void put(long index, byte value) {
@@ -243,7 +243,7 @@ public class PagedFileStorage implements Forceable {
int page_offset = (int) (i % myPageSize);
int page_len = Math.min(l, myPageSize - page_offset);
final ByteBuffer buffer = getBuffer(page, false);
final ByteBuffer buffer = getReadOnlyBuffer(page);
try {
buffer.position(page_offset);
}
@@ -369,28 +369,32 @@ public class PagedFileStorage implements Forceable {
}
private ByteBuffer getBuffer(long page) {
return getBuffer(page, true);
return getBufferWrapper(page, true).getCachedBuffer();
}
private ByteBuffer getBuffer(long page, boolean modify) {
private ByteBuffer getReadOnlyBuffer(long page) {
return getBufferWrapper(page, false).getCachedBuffer();
}
private ByteBufferWrapper getBufferWrapper(long page, boolean modify) {
synchronized (myLastAccessedBufferCacheLock) {
if (myLastPage == page) {
ByteBuffer buf = myLastBuffer.getCachedBuffer();
if (buf != null && myLastChangeCount == myStorageLockContext.myStorageLock.myMappingChangeCount) {
if (modify) markDirty(myLastBuffer);
return buf;
return myLastBuffer;
}
} else if (myLastPage2 == page) {
ByteBuffer buf = myLastBuffer2.getCachedBuffer();
if (buf != null && myLastChangeCount2 == myStorageLockContext.myStorageLock.myMappingChangeCount) {
if (modify) markDirty(myLastBuffer2);
return buf;
return myLastBuffer2;
}
} else if (myLastPage3 == page) {
ByteBuffer buf = myLastBuffer3.getCachedBuffer();
if (buf != null && myLastChangeCount3 == myStorageLockContext.myStorageLock.myMappingChangeCount) {
if (modify) markDirty(myLastBuffer3);
return buf;
return myLastBuffer3;
}
}
}
@@ -427,7 +431,7 @@ public class PagedFileStorage implements Forceable {
myLastChangeCount = myStorageLockContext.myStorageLock.myMappingChangeCount;
}
return buf;
return byteBufferWrapper;
}
catch (IOException e) {
throw new MappingFailedException("Cannot map buffer", e);