/** Lets go of any references to a hash map. */ public void forget() { hashMap = null; readPos = null; byteSegmentRef.reset(0, 0); hasRows = false; readIndex = 0; nextTailOffset = -1; }
/** * Read the current value. * * @return The ByteSegmentRef to the current value read. */ private WriteBuffers.ByteSegmentRef internalRead() { if (!hasList) { /* * Single value. */ if (readIndex > 0) { return null; } // For a non-list (i.e. single value), the offset is for the variable length long (VLong) // holding the value length (followed by the key length). hashMap.writeBuffers.setReadPoint(firstOffset, readPos); int valueLength = (int) hashMap.writeBuffers.readVLong(readPos); // The value is before the offset. Make byte segment reference absolute. byteSegmentRef.reset(firstOffset - valueLength, valueLength); hashMap.writeBuffers.populateValue(byteSegmentRef); readIndex++; return byteSegmentRef; } /* * Multiple values. */ if (readIndex == 0) { // For a list, the value and key lengths of 1st record were overwritten with the // relative offset to a new list record. long relativeOffset = hashMap.writeBuffers.readNByteLong(firstOffset, 5, readPos); // At the beginning of the list record will be the value length. hashMap.writeBuffers.setReadPoint(firstOffset + relativeOffset, readPos); int valueLength = (int) hashMap.writeBuffers.readVLong(readPos); // The value is before the list record offset. Make byte segment reference absolute. byteSegmentRef.reset(firstOffset - valueLength, valueLength); hashMap.writeBuffers.populateValue(byteSegmentRef); readIndex++; return byteSegmentRef; } if (readIndex == 1) { // We remembered the offset of just after the key length in the list record. // Read the absolute offset to the 2nd value. nextTailOffset = hashMap.writeBuffers.readNByteLong(offsetAfterListRecordKeyLen, 5, readPos); if (nextTailOffset <= 0) { throw new Error("Expecting a second value"); } } else if (nextTailOffset <= 0) { return null; } hashMap.writeBuffers.setReadPoint(nextTailOffset, readPos); // Get the value length. int valueLength = (int) hashMap.writeBuffers.readVLong(readPos); // Now read the relative offset to next record. Next record is always before the // previous record in the write buffers (see writeBuffers javadoc). long delta = hashMap.writeBuffers.readVLong(readPos); long newTailOffset = delta == 0 ? 0 : (nextTailOffset - delta); // The value is before the value record offset. Make byte segment reference absolute. byteSegmentRef.reset(nextTailOffset - valueLength, valueLength); hashMap.writeBuffers.populateValue(byteSegmentRef); nextTailOffset = newTailOffset; readIndex++; return byteSegmentRef; }