void writeIndexSegmentToFile(Offset safeEndPoint) throws FileNotFoundException, StoreException {
    if (sealed.get()) {
      logger.trace("Cannot persist sealed index segment : {}", indexFile.getAbsolutePath());
      return;
    }
    if (safeEndPoint.compareTo(startOffset) <= 0) {
      return;
    }
    if (!safeEndPoint.equals(prevSafeEndPoint)) {
      if (safeEndPoint.compareTo(getEndOffset()) > 0) {
        throw new StoreException(
            "SafeEndOffSet " + safeEndPoint + " is greater than current end offset for current " + "index segment "
                + getEndOffset(), StoreErrorCodes.IllegalIndexOperation);
      }
      File temp = new File(getFile().getAbsolutePath() + ".tmp");
      FileOutputStream fileStream = new FileOutputStream(temp);
      CrcOutputStream crc = new CrcOutputStream(fileStream);
      rwLock.readLock().lock();
      try (DataOutputStream writer = new DataOutputStream(crc)) {
        writer.writeShort(getVersion());
        if (getVersion() >= PersistentIndex.VERSION_2) {
          writer.writeInt(maxEntrySize);
        } else {
          // write the key size
          writer.writeInt(maxEntrySize - getValueSize());
        }
        writer.writeInt(getValueSize());
        writer.writeLong(safeEndPoint.getOffset());
        if (getVersion() != PersistentIndex.VERSION_0) {
          // write last modified time and reset key in case of version != 0
          writer.writeLong(lastModifiedTimeSec.get());
          writer.write(resetKeyInfo.getResetKey().toBytes());
          writer.writeShort(resetKeyInfo.getResetKeyType().ordinal());
        }
        if (getVersion() >= PersistentIndex.VERSION_4) {
          // write reset key life version
          writer.writeShort(resetKeyInfo.getResetKeyLifeVersion());
        }

        byte[] maxPaddingBytes = null;
        if (getVersion() >= PersistentIndex.VERSION_2) {
          maxPaddingBytes = new byte[maxEntrySize - valueSize];
        }
        if (index != null) {
          for (Map.Entry<StoreKey, ConcurrentSkipListSet<IndexValue>> entry : index.entrySet()) {
            for (IndexValue value : entry.getValue()) {
              if (value.getOffset().getOffset() + value.getSize() <= safeEndPoint.getOffset()) {
                writer.write(entry.getKey().toBytes());
                writer.write(value.getBytes().array());
                if (getVersion() >= PersistentIndex.VERSION_2) {
                  // Add padding if necessary
                  writer.write(maxPaddingBytes, 0, maxEntrySize - (entry.getKey().sizeInBytes() + valueSize));
                }
                logger.trace("IndexSegment : {} writing key - {} value - offset {} size {} fileEndOffset {}",
                    getFile().getAbsolutePath(), entry.getKey(), value.getOffset(), value.getSize(), safeEndPoint);
              }
            }
          }
        }
        prevSafeEndPoint = safeEndPoint;
        long crcValue = crc.getValue();
        writer.writeLong(crcValue);

        // flush and overwrite old file
        fileStream.getChannel().force(true);
        // swap temp file with the original file
        temp.renameTo(getFile());
        if (config.storeSetFilePermissionEnabled) {
          Files.setPosixFilePermissions(getFile().toPath(), config.storeDataFilePermission);
        }
      } catch (IOException e) {
        StoreErrorCodes errorCode = StoreException.resolveErrorCode(e);
        throw new StoreException(
            "IndexSegment : " + indexFile.getAbsolutePath() + " encountered " + errorCode.toString()
                + " while persisting index to disk", e, errorCode);
      } finally {
        rwLock.readLock().unlock();
      }
      logger.trace("IndexSegment : {} completed writing index to file {} {}", indexFile.getAbsolutePath(), valueSize,
          maxEntrySize);
    }
  }
Writes the index to a persistent file.

Those that are written in version 4 has the following format:

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| version | entrysize | valuesize | fileendpointer |  last modified time(in secs) | Reset key | Reset key type | Reset key version ...
|(2 bytes)|(4 bytes)  | (4 bytes) |    (8 bytes)   |     (4 bytes)                | (m bytes) |   ( 2 bytes)   |  (2 bytes)        ...
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ...   key 1    | value 1          | Padding    | ...  | key n     | value n           | Padding    | crc      |
    ...   (m bytes)| (valuesize bytes)| (var size) |      | (p bytes) | (valuesize bytes) | (var size) | (8 bytes)|
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         |<- - - - - (entrysize bytes) - - - - - ->|      |<- - - - - - (entrysize bytes)- - - - - - ->|

 version            - the index format version
 entrysize          - the total size of an entry (key + value + padding) in this index segment
 valuesize          - the size of the value in this index segment
 fileendpointer     - the log end pointer that pertains to the index being persisted
 last modified time - the last modified time of the index segment in secs
 reset key          - the reset key(StoreKey) of the index segment
 reset key type     - the reset key index entry type(PUT/DELETE/TTLUpdate/UNDELETE)
 reset key version  - the life version of reset key
 key n / value n    - the key and value entries contained in this index segment
 crc                - the crc of the index segment content

Those that are written in version 2 and 3 have the following format:

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| version | entrysize | valuesize | fileendpointer |  last modified time(in secs) | Reset key | Reset key type  ...
|(2 bytes)|(4 bytes)  | (4 bytes) |    (8 bytes)   |     (4 bytes)                | (m bytes) |   ( 2 bytes)    ...
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ...   key 1    | value 1          | Padding    | ...  | key n     | value n           | Padding    | crc      |
    ...   (m bytes)| (valuesize bytes)| (var size) |      | (p bytes) | (valuesize bytes) | (var size) | (8 bytes)|
        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         |<- - - - - (entrysize bytes) - - - - - ->|      |<- - - - - - (entrysize bytes)- - - - - - ->|

 version            - the index format version
 entrysize          - the total size of an entry (key + value + padding) in this index segment
 valuesize          - the size of the value in this index segment
 fileendpointer     - the log end pointer that pertains to the index being persisted
 last modified time - the last modified time of the index segment in secs
 reset key          - the reset key(StoreKey) of the index segment
 reset key type     - the reset key index entry type(PUT/DELETE/TTLUpdate/UNDELETE)
 key n / value n    - the key and value entries contained in this index segment
 crc                - the crc of the index segment content


Those that were written in version 1 have the following format
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| version | keysize | valuesize | fileendpointer |  last modified time(in secs) | Reset key | Reset key type
|(2 bytes)|(4 bytes)| (4 bytes) |    (8 bytes)   |     (4 bytes)                | (m bytes) |   ( 2 bytes)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                 ...  key 1          | value 1          |  ...  |   key n         | value n           | crc       |
                 ...  (keysize bytes)| (valuesize bytes)|       | (keysize bytes) | (valuesize bytes) | (8 bytes) |
                     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 version            - the index format version
 keysize            - the size of the key in this index segment
 valuesize          - the size of the value in this index segment
 fileendpointer     - the log end pointer that pertains to the index being persisted
 last modified time - the last modified time of the index segment in secs
 reset key          - the reset key(StoreKey) of the index segment
 reset key type     - the reset key index entry type(PUT/DELETE)
 key n / value n    - the key and value entries contained in this index segment
 crc                - the crc of the index segment content

Those that were written in version 0 have the following format
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| version | keysize | valuesize | fileendpointer |   key 1        | value 1          |  ...  |   key n          ...
|(2 bytes)|(4 bytes)| (4 bytes) |    (8 bytes)   | (keysize bytes)| (valuesize bytes)|       | (keysize bytes)  ...
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                         - - - - - - - - - - - - - - - -
                                                     ...  value n            | crc      |
                                                     ...  (valuesize  bytes) | (8 bytes)|
                                                         - - - - - - - - - - - - - - - -

 version         - the index format version
 keysize         - the size of the key in this index segment
 valuesize       - the size of the value in this index segment
 fileendpointer  - the log end pointer that pertains to the index being persisted
 key n / value n - the key and value entries contained in this index segment
 crc             - the crc of the index segment content

@param safeEndPoint the end point (that is relevant to this segment) until which the log has been flushed.
@throws FileNotFoundException
@throws StoreException
ambry-store/src/main/java/com/github/ambry/store/IndexSegment.java