@Override
    public void recover() {
        final List<MappedFile> mappedFiles = this.mappedFileQueue.getMappedFiles();
        if (!mappedFiles.isEmpty()) {
            int index = mappedFiles.size() - 3;
            if (index < 0) {
                index = 0;
            }

            MappedFile mappedFile = mappedFiles.get(index);
            ByteBuffer byteBuffer = mappedFile.sliceByteBuffer();
            int mappedFileOffset = 0;
            long processOffset = mappedFile.getFileFromOffset();
            while (true) {
                for (int i = 0; i < mappedFileSize; i += CQ_STORE_UNIT_SIZE) {
                    byteBuffer.position(i);
                    long offset = byteBuffer.getLong();
                    int size = byteBuffer.getInt();
                    byteBuffer.getLong();   //tagscode
                    byteBuffer.getLong();   //timestamp
                    long msgBaseOffset = byteBuffer.getLong();
                    short batchSize = byteBuffer.getShort();
                    if (offset >= 0 && size > 0 && msgBaseOffset >= 0 && batchSize > 0) {
                        mappedFileOffset += CQ_STORE_UNIT_SIZE;
                        this.maxMsgPhyOffsetInCommitLog = offset;
                    } else {
                        log.info("Recover current batch consume queue file over, " + "file:{} offset:{} size:{} msgBaseOffset:{} batchSize:{} mappedFileOffset:{}",
                            mappedFile.getFileName(), offset, size, msgBaseOffset, batchSize, mappedFileOffset);

                        if (mappedFileOffset != mappedFileSize) {
                            mappedFile.setWrotePosition(mappedFileOffset);
                            mappedFile.setFlushedPosition(mappedFileOffset);
                            mappedFile.setCommittedPosition(mappedFileOffset);
                        }

                        break;
                    }
                }

                index++;
                if (index >= mappedFiles.size()) {
                    log.info("Recover last batch consume queue file over, last mapped file:{} ", mappedFile.getFileName());
                    break;
                } else {
                    mappedFile = mappedFiles.get(index);
                    byteBuffer = mappedFile.sliceByteBuffer();
                    processOffset = mappedFile.getFileFromOffset();
                    mappedFileOffset = 0;
                    log.info("Recover next batch consume queue file: " + mappedFile.getFileName());
                }
            }

            processOffset += mappedFileOffset;
            mappedFileQueue.setFlushedWhere(processOffset);
            mappedFileQueue.setCommittedWhere(processOffset);
            mappedFileQueue.truncateDirtyFiles(processOffset);
            reviseMaxAndMinOffsetInQueue();
        }
    }
@Test
    public void testLoad() throws IOException {
        scq = new SparseConsumeQueue(topic, queueId, path, BatchConsumeQueue.CQ_STORE_UNIT_SIZE, defaultMessageStore);

        String file1 = UtilAll.offset2FileName(111111);
        String file2 = UtilAll.offset2FileName(222222);

        long phyOffset = 10;
        long queueOffset = 1;
        ByteBuffer bb = ByteBuffer.allocate(BatchConsumeQueue.CQ_STORE_UNIT_SIZE);
        fillByteBuf(bb, phyOffset, queueOffset);
        Files.createDirectories(Paths.get(path, topic, String.valueOf(queueId)));
        Files.write(Paths.get(path, topic, String.valueOf(queueId), file1), bb.array(),
            StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
        bb.clear();
        fillByteBuf(bb, phyOffset + 1, queueOffset + 1);
        Files.write(Paths.get(path, topic, String.valueOf(queueId), file2), bb.array(),
            StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

        scq.load();
        scq.recover();
        assertEquals(scq.get(queueOffset + 1).getPos(), phyOffset + 1);
    }