RocketMQ存储之MappedFileQueue

一、概述

上一篇我们分析了MappedFile的实现细节,MappedFile实现了文件内存映射的功能。本篇我们分析MappedFileQueue的实现。

MappedFileQueue的作用是:将多个MappedFile按顺序组织起来,并且提供MappedFile的“增删查”操作等作用。由于MappedFileQueue的实现逻辑并不复杂,本篇只分析一部分源码实现。

二、实现细节

首先来看一下MappedFileQueue的创建和加载:

    public MappedFileQueue(final String storePath, int mappedFileSize,
        AllocateMappedFileService allocateMappedFileService) {
   
        this.storePath = storePath;
        this.mappedFileSize = mappedFileSize;
        this.allocateMappedFileService = allocateMappedFileService;
    }

    public boolean load() {
   
        File dir = new File(this.storePath);
        File[] files = dir.listFiles();
        if (files != null) {
   
            // ascending order
            // 按顺序加载到队列中
            Arrays.sort(files);
            for (File file : files) {
   

                if (file.length() != this.mappedFileSize) {
   
                    log.warn(file + "\t" + file.length()
                        + " length not matched message store config value, please check it manually");
                    return false;
                }

                try {
   
                    MappedFile mappedFile = new MappedFile(file.getPath(), mappedFileSize);

                    mappedFile.setWrotePosition(this.mappedFileSize);
                    mappedFile.setFlushedPosition(this.mappedFileSize);
                    mappedFile.setCommittedPosition(this.mappedFileSize);
                    this.mappedFiles.add(mappedFile);
                    log.info("load " + file.getPath() + " OK");
                } catch (IOException e) {
   
                    log.error("load file " + file + " error", e);
                    return false;
                }
            }
        }

        return true;
    }

实现过程很简单:将指定文件夹下的所有文件都加载映射为MappedFile,然后添加到队列中。

根据时间获取MappedFile:

    /**
     * 获取第一个更新时间大于timestamp的MappedFile,没有的话就返回最新的MappedFile
     * @param timestamp
     * @return
     */
    public MappedFile getMappedFileByTime(final long timestamp) {
   
    	// mappedFiles队列的副本
        Object[] mfs = this.copyMappedFiles(0);

        if (null == mfs)
            return null;

        for (int i = 0; i < mfs.length; i++) {
   
            MappedFile mappedFile = (MappedFile) mfs[i];
            if (mappedFile.getLastModifiedTimestamp() >= timestamp) {
   
                return mappedFile;
            }
        }

        return (MappedFile) mfs[mfs.length - 1];
    }

根据更新时间获取MappedFile的实现很简单,通过遍历mappedFiles队列查找第一个修改时间大于timestamp的MappedFile对象并返回,如果没有,就返回队列中的最后一个对象。

删除大于offset的数据:

    /**
     *
     * 删除大于offset的记录
     * @param offset
     */
    public void truncateDirtyFiles(long offset) {
   
        List<MappedFile> willRemoveFiles = new ArrayList<MappedFile>();

        for (MappedFile file : this.mappedFiles) {
   
            // 当前file的最大offset
            long fileTailOffset = file.getFileFromOffset() + this.mappedFileSize;
            if (fileTailOffset > offset) {
   
                // 当前文件最大的offset大于offset,说明有需要删除的记录
                if (offset >= file.getFileFromOffset()) {
   
                    // 当前文件的最小offset小于等于offset,说明当前文件有部分记录需要删除

                    // 将MappedFile的三个指针都设置到offset对应的位置,使大于offset的数据可以被覆盖
                    file.setWrotePosition((int) (offset % th
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值