Skip to content

Commit

Permalink
Fix for encoded long buffer setELementVAlue getElementValue for bytes…
Browse files Browse the repository at this point in the history
… past end of buffer
  • Loading branch information
Sunjeet committed Jun 22, 2023
1 parent ab45e0d commit ea9ef51
Show file tree
Hide file tree
Showing 24 changed files with 47 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static FixedLengthData allocate(HollowBlobInput in,
public static FixedLengthData allocate(long numBits, MemoryMode memoryMode, ArraySegmentRecycler memoryRecycler,
String fileName) throws IOException {
long numLongs = ((numBits - 1) >>> 6) + 1;
numLongs ++; // accommodate for reading a long starting at bit index within numLongs-1
long numBytes = numLongs << 3;
if (memoryMode.equals(MemoryMode.ON_HEAP)) {
return new FixedLengthElementArray(memoryRecycler, numBits);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private void writeRaf(int b) throws IOException {
raf.write(b);
}

// unused
public void resize(long sizeInBytes) throws IOException {
if (memoryMode.equals(MemoryMode.ON_HEAP)) {
// TODO: NOP because array is resized dynamically
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public byte getByte(long index) throws BufferUnderflowException {
}
else {
assert(index < capacity + Long.BYTES);
LOG.warning("SNAP: This is happening, not necessarily bad but test using unit test readUsingVariableLengthDataModes");
// this situation occurs when read for bits near the end of the buffer requires reading a long value that
// extends past the buffer capacity by upto Long.BYTES bytes. To handle this case,
// return 0 for (index >= capacity - Long.BYTES && index < capacity )
Expand Down Expand Up @@ -212,29 +213,16 @@ public int putBytes(long index, long len, byte[] bytes, boolean restorePos) {
}

public void putByte(long index, byte value) {
if (index < 0 || index >= (this.capacity+1) << 6) {
if (index < 0 || index >= (this.capacity+1) << 6) { // SNAP: can test using testIncrement or testSimpleParity
throw new IllegalStateException("Attempting to write a byte out of bounds");
}

if (index < capacity) {
int spineIndex = (int)(index >>> (shift));
int bufferIndex = (int)(index & mask);
int spineIndex = (int)(index >>> (shift));
int bufferIndex = (int)(index & mask);
try {
spine[spineIndex].put(bufferIndex, value);
}
else {
assert(index < capacity + Long.BYTES);
// this situation occurs when write for bits near the end of the buffer requires writing a long value that
// extends past the buffer capacity by upto Long.BYTES bytes. To handle this case, ignore writes to
// (index >= capacity - Long.BYTES && index < capacity )
// these zero bytes will be discarded anyway when the returned long value is shifted to get the queried bits
// these bytes should not hold a value
if (value != 0) {
if (index > capacity + Long.BYTES) { // SNAP: can make check more strict
throw new IllegalStateException("Attempting to write a byte beyond the max buffer capacity");
// SNAP: TODO: move the inner check, and validate that value should be 0 or else those writes will be lost
// Just that that'll fail the testCopyBitRange unit test, but probably the right thing to do.
}
}
} catch (IndexOutOfBoundsException e) {
System.out.println("here");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ public void prepareForNextCycle() {
overridePreviousHeaderTags(headerTags);

try {
// SNAP: TODO: creates 1 thread per processor
SimultaneousExecutor executor = new SimultaneousExecutor(getClass(), "prepare-for-next-cycle");

for(final Map.Entry<String, HollowTypeWriteState> typeStateEntry : writeStates.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.netflix.hollow.core.memory.encoding;

import com.netflix.hollow.core.memory.pool.WastefulRecycler;
import com.netflix.hollow.core.read.HollowBlobInput;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -37,14 +38,18 @@ public void writeThenRead() throws IOException {
}
}

EncodedLongBuffer setupEncodedLongBuffer(int fileSizeInBytes, int singleBufferCapacity) throws IOException {
// SNAP: TODO: here
EncodedLongBuffer setupEncodedLongBuffer(long numBits, int singleBufferCapacity) throws IOException {
long numLongs = ((numBits - 1) >>> 6) + 1;
numLongs ++;
long numBytes = numLongs * Long.BYTES;
File targetFile = new File("test-EncodedLongBuffer-" + System.currentTimeMillis() + "-" + RandomUtils.nextInt());
targetFile.deleteOnExit();
RandomAccessFile raf = new RandomAccessFile(targetFile, "rw");
raf.setLength(fileSizeInBytes);
raf.setLength(numBytes);
raf.close();
HollowBlobInput hbi = HollowBlobInput.randomAccess(targetFile, singleBufferCapacity);
EncodedLongBuffer buf = EncodedLongBuffer.newFrom(hbi, (fileSizeInBytes >> 3));
EncodedLongBuffer buf = EncodedLongBuffer.newFrom(hbi, numLongs);
return buf;
}

Expand Down Expand Up @@ -107,8 +112,8 @@ public void testCopyBitRange() throws IOException {
int copyFromRangeStartBit = rand.nextInt(totalBitsInArray - totalBitsInCopyRange);
int copyToRangeStartBit = rand.nextInt(100000);

EncodedLongBuffer source = setupEncodedLongBuffer((totalBitsInArray >> 3) + 1, singleBufferCapacity);
EncodedLongBuffer dest = setupEncodedLongBuffer((totalBitsInArray + copyToRangeStartBit >> 3) + 1, singleBufferCapacity);
EncodedLongBuffer source = setupEncodedLongBuffer(totalBitsInArray, singleBufferCapacity);
EncodedLongBuffer dest = setupEncodedLongBuffer(totalBitsInArray + copyToRangeStartBit, singleBufferCapacity);

int numLongs = (totalBitsInArray >>> 6);

Expand Down Expand Up @@ -140,8 +145,8 @@ public void testCopyBitRange() throws IOException {
@Test
public void testCopySmallBitRange() throws IOException {
int singleBufferCapacity = 1024;
EncodedLongBuffer bufFrom = setupEncodedLongBuffer((64 >> 3) + 1, singleBufferCapacity);
EncodedLongBuffer bufTo = setupEncodedLongBuffer((128 >> 3) + 1, singleBufferCapacity);
EncodedLongBuffer bufFrom = setupEncodedLongBuffer(64, singleBufferCapacity);
EncodedLongBuffer bufTo = setupEncodedLongBuffer(128, singleBufferCapacity);


bufFrom.setElementValue(0, 64, -1L);
Expand All @@ -154,32 +159,47 @@ public void testCopySmallBitRange() throws IOException {

}

@Test
public void testSimpleParity() throws Exception {
FixedLengthElementArray arr = new FixedLengthElementArray(WastefulRecycler.SMALL_ARRAY_RECYCLER, 1000000);
EncodedLongBuffer buf = setupEncodedLongBuffer(1000000, 1024);

arr.setElementValue(999960, 60, 1700037421l);
buf.setElementValue(999960, 60, 1700037421l);

long l1 = arr.getElementValue(999960, 60);
long l2 = buf.getElementValue(999960, 60);

assert (l1 == l2);

}

@Test
public void testIncrement() throws IOException {
int singleBufferCapacity = 1024;
int numBits = 1000000;
EncodedLongBuffer buf = setupEncodedLongBuffer((numBits >> 3) + 1, singleBufferCapacity);
EncodedLongBuffer buf = setupEncodedLongBuffer(numBits, singleBufferCapacity);

Random rand = new Random();

long startVal = rand.nextInt(Integer.MAX_VALUE);
int elementCount = 0;

for(int i=0;i<1000000-64;i+=65) {
for(int i=0;i<1000000;i+=65) {
buf.setElementValue(i, 60, startVal+i);
elementCount++;
}

buf.incrementMany(0, 1000, 65, elementCount);

for(int i=0;i<1000000-64;i+=65) {
for(int i=0;i<1000000;i+=65) {
long val = buf.getElementValue(i, 60);
Assert.assertEquals(startVal + i + 1000, val);
}

buf.incrementMany(0, -2000, 65, elementCount);

for(int i=0;i<1000000-64;i+=65) {
for(int i=0;i<1000000;i+=65) {
long val = buf.getElementValue(i, 60);
Assert.assertEquals(startVal + i - 1000, val);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,28 +257,29 @@ public void testCopySmallBitRange() {

@Test
public void testIncrement() {
FixedLengthElementArray arr = new FixedLengthElementArray(WastefulRecycler.SMALL_ARRAY_RECYCLER, 1000000);
FixedLengthElementArray arr = new FixedLengthElementArray(WastefulRecycler.SMALL_ARRAY_RECYCLER, 1000192);

Random rand = new Random();

long startVal = rand.nextInt(Integer.MAX_VALUE);
int elementCount = 0;

for(int i=0;i<1000000-64;i+=65) {
// for(int i=0;i<1000192;i+=65) { // SNAP: TODO: This will attempt to write past the long array capacity
for(int i=0;i<1000000;i+=65) {
arr.setElementValue(i, 60, startVal+i);
elementCount++;
}

arr.incrementMany(0, 1000, 65, elementCount);

for(int i=0;i<1000000-64;i+=65) {
for(int i=0;i<1000000;i+=65) {
long val = arr.getElementValue(i, 60);
Assert.assertEquals(startVal + i + 1000, val);
}

arr.incrementMany(0, -2000, 65, elementCount);

for(int i=0;i<1000000-64;i+=65) {
for(int i=0;i<1000000;i+=65) {
long val = arr.getElementValue(i, 60);
Assert.assertEquals(startVal + i - 1000, val);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private void readUsingVariableLengthDataModes(File testFile, int padding) throws
assertEquals(testByteArray.get(13 + padding), testByteBuffer.get(13 + padding));
assertEquals(testByteArray.get(127 + padding), testByteBuffer.get(127 + padding));

// SNAP: TODO: // out of bounds read
// uncomment to test BlobByteBufferTest::getByte()
// try {
// testByteBuffer.get(testFile.length());
// Assert.fail();
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit ea9ef51

Please sign in to comment.