void createOQLIndexes(InternalRegionArguments internalRegionArgs, boolean recoverFromDisk) {
    if (internalRegionArgs == null || internalRegionArgs.getIndexes() == null
        || internalRegionArgs.getIndexes().isEmpty()) {
      return;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("LocalRegion.createOQLIndexes on region {}", getFullPath());
    }
    long start = getCachePerfStats().startIndexInitialization();
    List oqlIndexes = internalRegionArgs.getIndexes();

    DiskRegion dr = getDiskRegion();
    boolean isOverflowToDisk = false;
    if (dr != null) {
      isOverflowToDisk = dr.isOverflowEnabled();
      if (recoverFromDisk && !isOverflowToDisk) {
        // For disk regions, index creation should wait for async value creation to complete before
        // it starts its iteration
        // In case of disk overflow regions the waitForAsyncRecovery is done in populateOQLIndexes
        // method via getBestIterator()
        dr.waitForAsyncRecovery();
      }
    }
    Set<Index> indexes = new HashSet<>();
    Set<Index> prIndexes = new HashSet<>();
    // Release the initialization latch for index creation.
    final InitializationLevel initLevel = setThreadInitLevelRequirement(ANY_INIT);
    try {
      for (Object o : oqlIndexes) {
        IndexCreationData icd = (IndexCreationData) o;
        try {
          if (icd.getPartitionedIndex() != null) {
            createOQLIndexOnPartitionedRegion(internalRegionArgs, isOverflowToDisk, indexes,
                prIndexes, icd);
          } else {
            if (logger.isDebugEnabled()) {
              logger.debug("QueryService Index creation process for {}" + icd.getIndexName());
            }
            DefaultQueryService qs = (DefaultQueryService) getGemFireCache().getLocalQueryService();
            String fromClause =
                icd.getIndexType() == IndexType.FUNCTIONAL || icd.getIndexType() == IndexType.HASH
                    ? icd.getIndexFromClause() : getFullPath();
            // load entries during initialization only for non overflow regions
            indexes.add(
                qs.createIndex(icd.getIndexName(), icd.getIndexType(), icd.getIndexExpression(),
                    fromClause, icd.getIndexImportString(), !isOverflowToDisk));
          }

        } catch (Exception ex) {
          logger.info("Failed to create index {} on region {} with exception: {}",
              icd.getIndexName(), getFullPath(), ex);

        }
      }
    } finally {
      // Reset the initialization lock.
      setThreadInitLevelRequirement(initLevel);
    }
    // Load data into OQL indexes in case of disk recovery and disk overflow
    if (isOverflowToDisk) {
      if (recoverFromDisk) {
        populateOQLIndexes(indexes);
      } else {
        // Empty indexes are created for overflow regions but not populated at this stage
        // since this is not recovery.
        // Setting the populate flag to true so that the indexes can apply updates.
        indexManager.setPopulateFlagForIndexes(indexes);
      }
      // the pr index populate flags were not being set
      // we should revisit and clean up the index creation code paths
      indexManager.setPopulateFlagForIndexes(prIndexes);
    }
    getCachePerfStats().endIndexInitialization(start);
  }
Do any extra initialization required. Region is already visible in parent's subregion map. This
method releases the initialization Latches, so subclasses should call this super method last
after performing additional initialization.

@param imageTarget ignored, used by subclass for get initial image
@see DistributedRegion#initialize(InputStream, InternalDistributedMember,
     InternalRegionArguments)
geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java