public void endRecovery() throws WALRecoverException {
    // skip update info when this TsFile is not crashed
    if (hasCrashed()) {
      IMemTable recoveryMemTable = walRedoer.getRecoveryMemTable();
      // update time map
      Map<IDeviceID, IWritableMemChunkGroup> memTableMap = recoveryMemTable.getMemTableMap();
      for (Map.Entry<IDeviceID, IWritableMemChunkGroup> deviceEntry : memTableMap.entrySet()) {
        IDeviceID deviceId = deviceEntry.getKey();
        for (Map.Entry<String, IWritableMemChunk> measurementEntry :
            deviceEntry.getValue().getMemChunkMap().entrySet()) {
          IWritableMemChunk memChunk = measurementEntry.getValue();
          tsFileResource.updateStartTime(deviceId, memChunk.getFirstPoint());
          tsFileResource.updateEndTime(deviceId, memChunk.getLastPoint());
        }
      }
      // flush memTable
      try {
        if (!recoveryMemTable.isEmpty() && recoveryMemTable.getSeriesNumber() != 0) {
          MemTableFlushTask tableFlushTask =
              new MemTableFlushTask(
                  recoveryMemTable,
                  writer,
                  databaseName + FILE_NAME_SEPARATOR + dataRegionId,
                  dataRegionId);
          tableFlushTask.syncFlushMemTable();
          tsFileResource.updatePlanIndexes(recoveryMemTable.getMinPlanIndex());
          tsFileResource.updatePlanIndexes(recoveryMemTable.getMaxPlanIndex());
        }

        // set recover progress index for pipe
        PipeDataNodeAgent.runtime().assignProgressIndexForTsFileRecovery(tsFileResource);

        try {
          long memTableSize = recoveryMemTable.memSize();
          double compressionRatio = ((double) memTableSize) / writer.getPos();
          logger.info(
              "The compression ratio of tsfile {} is {}, totalMemTableSize: {}, the file size: {}",
              writer.getFile().getAbsolutePath(),
              String.format("%.2f", compressionRatio),
              memTableSize,
              writer.getPos());
          CompressionRatio.getInstance().updateRatio(memTableSize, writer.getPos());
        } catch (IOException e) {
          logger.error(
              "{}: {} update compression ratio failed",
              databaseName,
              tsFileResource.getTsFile().getName(),
              e);
        }

        // if we put following codes in the 'if' clause above, this file can be continued writing
        // into it
        // currently, we close this file anyway
        writer.endFile();
        tsFileResource.serialize();
        FileTimeIndexCacheRecorder.getInstance().logFileTimeIndex(tsFileResource);
      } catch (IOException | ExecutionException e) {
        throw new WALRecoverException(e);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new WALRecoverException(e);
      }
    }

    // return this TsFile back to vsg processor
    callbackAfterUnsealedTsFileRecovered.accept(this);
  }
Run last procedures to end this recovery.

@throws WALRecoverException when failing to flush the recovered memTable.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/file/UnsealedTsFileRecoverPerformer.java