private RecoverResult recoverData(long checkOffset) throws IOException {
        if (!this.mutable) {
            throw new UnsupportedOperationException(
                    "[File Store] The Data Segment must be mutable!");
        }
        final long totalBytes = this.channel.size();
        if (totalBytes == checkOffset || checkOffset == -1) {
            this.cachedSize.set(totalBytes);
            this.flushedSize.set(totalBytes);
            this.channel.position(totalBytes);
            return new RecoverResult(0, totalBytes == checkOffset);
        }
        long validBytes = 0L;
        long next = 0L;
        long itemRead = 0L;
        int itemMsglen = 0;
        int itemMsgToken = 0;
        int itemCheckSum = 0;
        long itemNext = 0L;
        final ByteBuffer itemBuf = ByteBuffer.allocate(DataStoreUtils.STORE_DATA_HEADER_LEN);
        do {
            do {
                itemBuf.rewind();
                itemRead = this.channel.read(itemBuf);
                if (itemRead < DataStoreUtils.STORE_DATA_HEADER_LEN) {
                    next = -1;
                    break;
                }
                itemBuf.flip();
                itemMsglen = itemBuf.getInt() - DataStoreUtils.STORE_DATA_PREFX_LEN;
                itemMsgToken = itemBuf.getInt();
                itemCheckSum = itemBuf.getInt();
                itemNext = validBytes + DataStoreUtils.STORE_DATA_HEADER_LEN + itemMsglen;
                if ((itemMsgToken != DataStoreUtils.STORE_DATA_TOKER_BEGIN_VALUE)
                        || (itemMsglen <= 0)
                        || (itemMsglen > DataStoreUtils.MAX_MSG_DATA_STORE_SIZE)
                        || (itemNext > totalBytes)) {
                    next = -1;
                    break;
                }
                final ByteBuffer messageBuffer = ByteBuffer.allocate(itemMsglen);
                while (messageBuffer.hasRemaining()) {
                    itemRead = this.channel.read(messageBuffer);
                    if (itemRead < 0) {
                        throw new IOException(
                                "[File Store] The Data Segment is changing in recover processing!");
                    }
                }
                if (CheckSum.crc32(messageBuffer.array()) != itemCheckSum) {
                    next = -1;
                    break;
                }
                next = itemNext;
            } while (false);
            if (next >= 0) {
                validBytes = next;
            }
        } while (next >= 0);
        if (totalBytes != validBytes) {
            this.channel.truncate(validBytes);
        }
        this.cachedSize.set(validBytes);
        this.flushedSize.set(validBytes);
        this.channel.position(validBytes);
        return new RecoverResult(totalBytes - validBytes, false);
    }
Check whether this FileSegment is expired, and set expire status.
The last FileSegment cannot be marked expired.

@param checkTimestamp check timestamp.
@param maxValidTimeMs the max expire interval in milliseconds.
@return -1 means already expired, 0 means the last FileSegment, 1 means expired.
inlong-tubemq/tubemq-server/src/main/java/org/apache/inlong/tubemq/server/broker/msgstore/disk/FileSegment.java