/**
  * Writes the value and value length for non-first record.
  *
  * @param kv Key-value writer.
  * @return The offset of the new record.
  */
 private long writeValueAndLength(KvSource kv) throws SerDeException {
   long valueOffset = writeBuffers.getWritePoint();
   kv.writeValue(writeBuffers);
   long tailOffset = writeBuffers.getWritePoint();
   writeBuffers.writeVLong(tailOffset - valueOffset);
   // LOG.info("Writing value at " + valueOffset + " length " + (tailOffset - valueOffset));
   return tailOffset;
 }
 /**
  * Adds a newly-written record to existing list.
  *
  * @param lrPtrOffset List record pointer offset.
  * @param tailOffset New record offset.
  */
 private void addRecordToList(long lrPtrOffset, long tailOffset) {
   // Now, insert this record into the list.
   long prevHeadOffset = writeBuffers.readNByteLong(lrPtrOffset, 5);
   // LOG.info("Reading offset " + prevHeadOffset + " at " + lrPtrOffset);
   assert prevHeadOffset < tailOffset; // We replace an earlier element, must have lower offset.
   writeBuffers.writeFiveByteULong(lrPtrOffset, tailOffset);
   // LOG.info("Writing offset " + tailOffset + " at " + lrPtrOffset);
   writeBuffers.writeVLong(prevHeadOffset == 0 ? 0 : (tailOffset - prevHeadOffset));
 }
 /**
  * Writes first value and lengths to finish the first record after the key has been written.
  *
  * @param kv Key-value writer.
  * @param keyOffset
  * @param keyLength Key length (already written).
  * @param hashCode
  * @return The offset of the new record.
  */
 private long writeFirstValueRecord(KvSource kv, long keyOffset, int keyLength, int hashCode)
     throws SerDeException {
   long valueOffset = writeBuffers.getWritePoint();
   kv.writeValue(writeBuffers);
   long tailOffset = writeBuffers.getWritePoint();
   int valueLength = (int) (tailOffset - valueOffset);
   // LOG.info("Writing value at " + valueOffset + " length " + valueLength);
   // In an unlikely case of 0-length key and value for the very first entry, we want to tell
   // this apart from an empty value. We'll just advance one byte; this byte will be lost.
   if (tailOffset == 0) {
     writeBuffers.reserve(1);
     ++tailOffset;
   }
   // LOG.info("First tail offset " + writeBuffers.getWritePoint());
   writeBuffers.writeVLong(valueLength);
   writeBuffers.writeVLong(keyLength);
   long lengthsLength = writeBuffers.getWritePoint() - tailOffset;
   if (lengthsLength < 5) { // Reserve space for potential future list
     writeBuffers.reserve(5 - (int) lengthsLength);
   }
   // Finally write the hash code.
   writeBuffers.writeInt(keyOffset - 4, hashCode);
   return tailOffset;
 }