Index: src/java/org/apache/lucene/util/PagedBytes.java =================================================================== --- src/java/org/apache/lucene/util/PagedBytes.java (revision 1417024) +++ src/java/org/apache/lucene/util/PagedBytes.java (working copy) @@ -70,19 +70,16 @@ blockSize = pagedBytes.blockSize; } - /** + /** * Gets a slice out of {@link PagedBytes} starting at start with a - * given length. Iff the slice spans across a block border this method will + * given length. If the slice spans more than one block this method will * allocate sufficient resources and copy the paged data. - *

- * Slices spanning more than one block are not supported. - *

* @lucene.internal **/ public BytesRef fillSlice(BytesRef b, long start, int length) { assert length >= 0: "length=" + length; - assert length <= blockSize+1; - final int index = (int) (start >> blockBits); + assert length <= start+(blocks.length*blockSize)+1; + final int index = (int) (start/blockSize); final int offset = (int) (start & blockMask); b.length = length; if (blockSize - offset >= length) { @@ -90,15 +87,23 @@ b.bytes = blocks[index]; b.offset = offset; } else { - // Split + // Spans variable number of blocks b.bytes = new byte[length]; b.offset = 0; - System.arraycopy(blocks[index], offset, b.bytes, 0, blockSize-offset); - System.arraycopy(blocks[1+index], 0, b.bytes, blockSize-offset, length-(blockSize-offset)); + //Number of blocks that bytes must be sliced from + final int blockSpan = (length+offset-1)/blockSize; + //Length to copy from last block + final int tail = length-(blockSize-offset)-((blockSpan-1)*blockSize); + for (int i=0;i<=blockSpan;i++) { + System.arraycopy(blocks[i+index], (i == 0 ? offset : 0), b.bytes, //Only use offset for first block. + i*blockSize-(i != 0 ? offset : 0), + (i == blockSpan ? tail : blockSize)-(i == 0 ? offset : 0) //Use tail for last block. + ); + } } return b; } - + /** * Reads length as 1 or 2 byte vInt prefix, starting at start. *

Index: src/test/org/apache/lucene/util/TestPagedBytes.java =================================================================== --- src/test/org/apache/lucene/util/TestPagedBytes.java (revision 1417024) +++ src/test/org/apache/lucene/util/TestPagedBytes.java (working copy) @@ -165,4 +165,44 @@ assertEquals(offset+1, in.getPosition()); } } + + //Parameters for testing fillSlice + private final int testBlockBits = 4; //16 bytes per block + private final int testBlockCount = 4; + private final int testBlockSize = 1 << testBlockBits; + + private void testFillSlice(int start, int length) throws Exception { + Random random = random(); + final PagedBytes p = new PagedBytes(testBlockBits); + final DataOutput out = p.getDataOutput(); + final byte[] bytes = new byte[testBlockSize*testBlockCount]; + random.nextBytes(bytes); + out.writeBytes(bytes, 0, bytes.length); + + final PagedBytes.Reader reader = p.freeze(random.nextBoolean()); + BytesRef answer = reader.fillSlice(new BytesRef(), start, length); + assertEquals(length, answer.length); + + //Loop as long as the values are equal + int lastOffset = 0; + for(int i=0;i