@Override
  public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
    PostingsReaderBase postingsReader =
        new SepPostingsReader(
            state.dir,
            state.segmentInfo,
            state.context,
            new MockIntFactory(blockSize),
            state.segmentSuffix);

    TermsIndexReaderBase indexReader;
    boolean success = false;
    try {
      indexReader =
          new FixedGapTermsIndexReader(
              state.dir,
              state.fieldInfos,
              state.segmentInfo.name,
              state.termsIndexDivisor,
              BytesRef.getUTF8SortedAsUnicodeComparator(),
              state.segmentSuffix,
              IOContext.DEFAULT);
      success = true;
    } finally {
      if (!success) {
        postingsReader.close();
      }
    }

    success = false;
    try {
      FieldsProducer ret =
          new BlockTermsReader(
              indexReader,
              state.dir,
              state.fieldInfos,
              state.segmentInfo.name,
              postingsReader,
              state.context,
              1024,
              state.segmentSuffix);
      success = true;
      return ret;
    } finally {
      if (!success) {
        try {
          postingsReader.close();
        } finally {
          indexReader.close();
        }
      }
    }
  }
  @Override
  public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {

    final String seedFileName =
        IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, SEED_EXT);
    final IndexInput in = state.dir.openInput(seedFileName, state.context);
    final long seed = in.readLong();
    if (LuceneTestCase.VERBOSE) {
      System.out.println(
          "MockRandomCodec: reading from seg="
              + state.segmentInfo.name
              + " formatID="
              + state.segmentSuffix
              + " seed="
              + seed);
    }
    in.close();

    final Random random = new Random(seed);

    int readBufferSize = _TestUtil.nextInt(random, 1, 4096);
    if (LuceneTestCase.VERBOSE) {
      System.out.println("MockRandomCodec: readBufferSize=" + readBufferSize);
    }

    PostingsReaderBase postingsReader;

    if (random.nextBoolean()) {
      if (LuceneTestCase.VERBOSE) {
        System.out.println("MockRandomCodec: reading Sep postings");
      }
      postingsReader =
          new SepPostingsReader(
              state.dir,
              state.segmentInfo,
              state.context,
              new MockIntStreamFactory(random),
              state.segmentSuffix);
    } else {
      if (LuceneTestCase.VERBOSE) {
        System.out.println("MockRandomCodec: reading Standard postings");
      }
      postingsReader =
          new Lucene40PostingsReader(
              state.dir, state.segmentInfo, state.context, state.segmentSuffix);
    }

    if (random.nextBoolean()) {
      final int totTFCutoff = _TestUtil.nextInt(random, 1, 20);
      if (LuceneTestCase.VERBOSE) {
        System.out.println(
            "MockRandomCodec: reading pulsing postings with totTFCutoff=" + totTFCutoff);
      }
      postingsReader = new PulsingPostingsReader(postingsReader);
    }

    final FieldsProducer fields;

    if (random.nextBoolean()) {
      // Use BlockTree terms dict
      if (LuceneTestCase.VERBOSE) {
        System.out.println("MockRandomCodec: reading BlockTree terms dict");
      }

      boolean success = false;
      try {
        fields =
            new BlockTreeTermsReader(
                state.dir,
                state.fieldInfos,
                state.segmentInfo.name,
                postingsReader,
                state.context,
                state.segmentSuffix,
                state.termsIndexDivisor);
        success = true;
      } finally {
        if (!success) {
          postingsReader.close();
        }
      }
    } else {

      if (LuceneTestCase.VERBOSE) {
        System.out.println("MockRandomCodec: reading Block terms dict");
      }
      final TermsIndexReaderBase indexReader;
      boolean success = false;
      try {
        final boolean doFixedGap = random.nextBoolean();

        // randomness diverges from writer, here:
        if (state.termsIndexDivisor != -1) {
          state.termsIndexDivisor = _TestUtil.nextInt(random, 1, 10);
        }

        if (doFixedGap) {
          // if termsIndexDivisor is set to -1, we should not touch it. It means a
          // test explicitly instructed not to load the terms index.
          if (LuceneTestCase.VERBOSE) {
            System.out.println(
                "MockRandomCodec: fixed-gap terms index (divisor=" + state.termsIndexDivisor + ")");
          }
          indexReader =
              new FixedGapTermsIndexReader(
                  state.dir,
                  state.fieldInfos,
                  state.segmentInfo.name,
                  state.termsIndexDivisor,
                  BytesRef.getUTF8SortedAsUnicodeComparator(),
                  state.segmentSuffix,
                  state.context);
        } else {
          final int n2 = random.nextInt(3);
          if (n2 == 1) {
            random.nextInt();
          } else if (n2 == 2) {
            random.nextLong();
          }
          if (LuceneTestCase.VERBOSE) {
            System.out.println(
                "MockRandomCodec: variable-gap terms index (divisor="
                    + state.termsIndexDivisor
                    + ")");
          }
          indexReader =
              new VariableGapTermsIndexReader(
                  state.dir,
                  state.fieldInfos,
                  state.segmentInfo.name,
                  state.termsIndexDivisor,
                  state.segmentSuffix,
                  state.context);
        }

        success = true;
      } finally {
        if (!success) {
          postingsReader.close();
        }
      }

      final int termsCacheSize = _TestUtil.nextInt(random, 1, 1024);

      success = false;
      try {
        fields =
            new BlockTermsReader(
                indexReader,
                state.dir,
                state.fieldInfos,
                state.segmentInfo.name,
                postingsReader,
                state.context,
                termsCacheSize,
                state.segmentSuffix);
        success = true;
      } finally {
        if (!success) {
          try {
            postingsReader.close();
          } finally {
            indexReader.close();
          }
        }
      }
    }

    return fields;
  }