/** * Appends the contents of the ByteArraySegment to the DataFrame. * * @param data The ByteArraySegment to append. * @return The number of bytes written. If less than the length of the ByteArraySegment, the frame is full and cannot * write anything anymore. The remaining bytes will need to be written to a new frame. * @throws IllegalStateException If the frame is sealed or no entry has been started. */ int append(ByteArraySegment data) { ensureAppendConditions(); int actualLength = Math.min(data.getLength(), getAvailableLength()); if (actualLength > 0) { this.contents.copyFrom(data, writePosition, actualLength); writePosition += actualLength; } return actualLength; }
/** * Sets the Value at the given position. * * @param pos The Position to set the value at. * @param value A ByteArraySegment representing the value to set. */ private void setValueAtPosition(int pos, ByteArraySegment value) { Preconditions.checkElementIndex(pos, getCount(), "pos must be non-negative and smaller than the number of items."); Preconditions.checkArgument(value.getLength() == this.config.valueLength, "Given value has incorrect length."); this.data.copyFrom(value, pos * this.config.entryLength + this.config.keyLength, value.getLength()); }
/** * Updates the first PageEntry's key to the given value. * * @param newKey A ByteArraySegment representing the replacement value for the first key. This must be smaller than * or equal to the current value of the first key (using KEY_COMPARATOR). */ void setFirstKey(ByteArraySegment newKey) { Preconditions.checkState(getCount() > 0, "BTreePage is empty. Cannot set first key."); Preconditions.checkArgument(newKey.getLength() == this.config.getKeyLength(), "Incorrect key length."); Preconditions.checkArgument(KEY_COMPARATOR.compare(newKey, getKeyAt(0)) <= 0, "Replacement first Key must be smaller than or equal to the existing first key."); this.data.copyFrom(newKey, 0, newKey.getLength()); }
/** * Creates a new instance of the BTreePage class wrapping the given Data Items (no header or footer). * * @param config Page Configuration. * @param count Number of items in data. * @param data A ByteArraySegment containing a list of Key-Value pairs to include. The contents of this ByteArraySegment * will be copied into a new buffer, so changes to this BTreePage will not affect it. */ private BTreePage(Config config, int count, ByteArraySegment data) { this(config, new ByteArraySegment(new byte[DATA_OFFSET + data.getLength() + FOOTER_LENGTH]), false); Preconditions.checkArgument(count * config.entryLength == data.getLength(), "Unexpected data length given the count."); formatHeaderAndFooter(count, ID_GENERATOR.nextInt()); this.data.copyFrom(data, 0, data.getLength()); }
private void setEntryAtIndex(int dataIndex, PageEntry entry) { Preconditions.checkElementIndex(dataIndex, this.data.getLength(), "dataIndex must be non-negative and smaller than the size of the data."); Preconditions.checkArgument(entry.getKey().getLength() == this.config.keyLength, "Given entry key has incorrect length."); Preconditions.checkArgument(entry.getValue().getLength() == this.config.valueLength, "Given entry value has incorrect length."); this.data.copyFrom(entry.getKey(), dataIndex, entry.getKey().getLength()); this.data.copyFrom(entry.getValue(), dataIndex + this.config.keyLength, entry.getValue().getLength()); }
/** * Tests the functionality of copyFrom. */ @Test public void testCopyFrom() { final byte[] sourceBuffer = createFormattedBuffer(); final int targetOffset = 11; final byte[] targetBuffer = new byte[sourceBuffer.length + targetOffset]; final int copyLength = sourceBuffer.length - 7; ByteArraySegment source = new ByteArraySegment(sourceBuffer); ByteArraySegment target = new ByteArraySegment(targetBuffer); // Copy second part. target.copyFrom(source, targetOffset, copyLength); for (int i = 0; i < targetBuffer.length; i++) { int expectedValue = i < targetOffset || i >= targetOffset + copyLength ? 0 : i - targetOffset; Assert.assertEquals("Unexpected value after copyFrom (1) in segment at offset " + i, expectedValue, target.get(i)); Assert.assertEquals("Unexpected value after copyFrom (1) in base buffer at offset " + i, expectedValue, targetBuffer[i]); } // Test copyFrom with source offset. Arrays.fill(targetBuffer, (byte) 0); final int sourceOffset = 3; target.copyFrom(source, sourceOffset, targetOffset, copyLength); for (int i = 0; i < targetBuffer.length; i++) { int expectedValue = i < targetOffset || i >= targetOffset + copyLength ? 0 : (i - targetOffset + sourceOffset); Assert.assertEquals("Unexpected value after copyFrom (2) in segment at offset " + i, expectedValue, target.get(i)); Assert.assertEquals("Unexpected value after copyFrom (2) in base buffer at offset " + i, expectedValue, targetBuffer[i]); } }
/** * Tests the behavior of the ByteArraySegment in read-only mode. */ @Test public void testReadOnly() throws Exception { final byte[] buffer = createFormattedBuffer(); ByteArraySegment segment = new ByteArraySegment(buffer, 0, buffer.length, true); // Check the isReadonly flag Assert.assertTrue("Unexpected value for isReadOnly() for read-only segment.", segment.isReadOnly()); Assert.assertFalse("Unexpected value for isReadOnly() for non-read-only segment.", new ByteArraySegment(buffer).isReadOnly()); // Verify that "mutator" methods do not work. checkReadOnlyException("copyFrom", () -> segment.copyFrom(new ByteArraySegment(new byte[10], 0, 10), 0, 10)); checkReadOnlyException("getWriter", segment::getWriter); checkReadOnlyException("set", () -> segment.set(0, (byte) 0)); // Check to see that, even though we did get an exception, the buffer was not modified. for (int i = 0; i < buffer.length; i++) { Assert.assertEquals("One of the 'mutator' methods modified the buffer at index " + i, i, buffer[i]); } // Check that a subsegment is also read-only. Assert.assertTrue("Unexpected value for isReadOnly() for read-only sub-segment.", segment.subSegment(0, 1).isReadOnly()); Assert.assertTrue("Unexpected value for isReadOnly() for read-only sub-segment from non-read-only segment (when attempting to create a non-read-only segment).", segment.subSegment(0, 1, false).isReadOnly()); Assert.assertTrue("Unexpected value for isReadOnly() for read-only sub-segment from non-read-only segment.", new ByteArraySegment(buffer).subSegment(0, 1, true).isReadOnly()); }