public synchronized void write() throws StoreException {
      final Timer.Context context = metrics.indexFlushTime.time();
      try {
        ConcurrentSkipListMap<Offset, IndexSegment> indexSegments = validIndexSegments;
        Map.Entry<Offset, IndexSegment> lastEntry = indexSegments.lastEntry();
        if (lastEntry != null) {
          IndexSegment currentInfo = lastEntry.getValue();
          // before iterating the map, get the current file end pointer
          Offset indexEndOffsetBeforeFlush = currentInfo.getEndOffset();
          Offset logEndOffsetBeforeFlush = log.getEndOffset();
          if (logEndOffsetBeforeFlush.compareTo(indexEndOffsetBeforeFlush) < 0) {
            throw new StoreException("LogEndOffset " + logEndOffsetBeforeFlush + " before flush cannot be less than "
                + "currentEndOffSet of index " + indexEndOffsetBeforeFlush, StoreErrorCodes.IllegalIndexState);
          }

          if (hardDeleter != null) {
            hardDeleter.preLogFlush();
            // flush the log to ensure everything till the fileEndPointerBeforeFlush is flushed
            log.flush();
            hardDeleter.postLogFlush();
          } else {
            log.flush();
          }

          Map.Entry<Offset, IndexSegment> prevEntry = indexSegments.lowerEntry(lastEntry.getKey());
          IndexSegment prevInfo = prevEntry != null ? prevEntry.getValue() : null;
          List<IndexSegment> prevInfosToWrite = new ArrayList<>();
          Offset currentLogEndPointer = log.getEndOffset();
          while (prevInfo != null && !prevInfo.isSealed()) {
            if (prevInfo.getEndOffset().compareTo(currentLogEndPointer) > 0) {
              String message = "The read only index cannot have a file end pointer " + prevInfo.getEndOffset()
                  + " greater than the log end offset " + currentLogEndPointer;
              throw new StoreException(message, StoreErrorCodes.IllegalIndexState);
            }
            prevInfosToWrite.add(prevInfo);
            Map.Entry<Offset, IndexSegment> infoEntry = indexSegments.lowerEntry(prevInfo.getStartOffset());
            prevInfo = infoEntry != null ? infoEntry.getValue() : null;
          }
          for (int i = prevInfosToWrite.size() - 1; i >= 0; i--) {
            IndexSegment toWrite = prevInfosToWrite.get(i);
            logger.trace("Index : {} writing prev index with end offset {}", dataDir, toWrite.getEndOffset());
            toWrite.writeIndexSegmentToFile(toWrite.getEndOffset());
            toWrite.seal();
          }
          // Compaction may seal the current last index segment.
          currentInfo.writeIndexSegmentToFile(indexEndOffsetBeforeFlush);
        }
      } catch (FileNotFoundException e) {
        throw new StoreException("File not found while writing index to file", e, StoreErrorCodes.FileNotFound);
      } catch (IOException e) {
        StoreErrorCodes errorCode = StoreException.resolveErrorCode(e);
        throw new StoreException(errorCode.toString() + " while persisting index to disk", e, errorCode);
      } finally {
        context.stop();
      }
    }
Writes all the individual index segments to disk. It flushes the log before starting the
index flush. The penultimate index segment is flushed if it is not already flushed and mapped.
The last index segment is flushed whenever write is invoked.
@throws StoreException
ambry-store/src/main/java/com/github/ambry/store/PersistentIndex.java