zoukankan      html  css  js  c++  java
  • RocketMQ-创建MappedFile本地文件

    了解RocketMQ的都知道,它会保存所有的消息到本地文件。这个文件就是 MappedFile,每一个文件对应一个MappedFile.默认情况下大小位1g。

    在MessageStoreConfig中的mapedFileSizeCommitLog设置,当然一半情况下是通过配置文件来设置的。文件路劲也都是在这个配置类里。

    文件名格式是20位的数字,在这个类里生成,类似这样的(00000001000000000000 00100000000000000000 09000000000020000000):

    MappedFile由MappedFileQueue管理,下面是用来生成文件的方法:

       /**
         * 获取最后一个 MappedFile,若不存在或文件已满,则进行创建。
         * @param startOffset
         * @param needCreate
         * @return
         */
        public MapedFile getLastMapedFile(final long startOffset, boolean needCreate) {
            // 这个offeset是所有MappedFile的全局offset
            long createOffset = -1; // 创建文件开始offset。-1时,不创建
            MapedFile mapedFileLast = null;
            {
                this.readWriteLock.readLock().lock();
                if (this.mapedFiles.isEmpty()) {    // 一个映射文件都不存在
                    createOffset = startOffset - (startOffset % this.mapedFileSize);
                } else {
                    // 如果存在MappedFile对象,则获取最后一个List<MapedFile> mapedFiles = new ArrayList<MapedFile>()
                    mapedFileLast = this.mapedFiles.get(this.mapedFiles.size() - 1);
                }
                this.readWriteLock.readLock().unlock();
            }
    
            if (mapedFileLast != null && mapedFileLast.isFull()) {  // 最后一个文件已满
                // 通过这里你可以知道这个offset是所有文件的offse,而不是一个mappedfile的offset
                createOffset = mapedFileLast.getFileFromOffset() + this.mapedFileSize;
            }
    
            // 创建文件
            if (createOffset != -1 && needCreate) {
                // 计算文件名。从此处我们可 以得知,MappedFile的文件命名规则:
                // 00000001000000000000 00100000000000000000 09000000000020000000二十位
                // fileName[n] = fileName[n - 1] + n * mappedFileSize fileName[0] = startOffset - (startOffset % this.mappedFileSize)
                String nextFilePath = this.storePath + File.separator + UtilAll.offset2FileName(createOffset);
                log.info("shang's log >>> create mappedFile nextFilePath:{}",nextFilePath);
                String nextNextFilePath =
                        this.storePath + File.separator
                                + UtilAll.offset2FileName(createOffset + this.mapedFileSize);
                //  下一个文件的地址都算出来了,也对,就新建的时候可以直接加一个mapedfilesize来计算,就是1g。1024*1024*1024
                log.info("shang's log >>> nextNextFilePath:{}",nextNextFilePath);
    
                MapedFile mapedFile = null;
    
                // 两种方式创建文件
                if (this.allocateMapedFileService != null) {
                    mapedFile =
                            this.allocateMapedFileService.putRequestAndReturnMapedFile(nextFilePath,
                                    nextNextFilePath, this.mapedFileSize);
                } else {
                    try {
                        mapedFile = new MapedFile(nextFilePath, this.mapedFileSize);
                    } catch (IOException e) {
                        log.error("create mapedfile exception", e);
                    }
                }
    
                if (mapedFile != null) {
                    this.readWriteLock.writeLock().lock();
                    if (this.mapedFiles.isEmpty()) {
                        mapedFile.setFirstCreateInQueue(true);
                    }
                    this.mapedFiles.add(mapedFile);
                    this.readWriteLock.writeLock().unlock();
                }
    
                return mapedFile;
            }
    
            return mapedFileLast;
        }

    有两种方式生成mappedfile文件,第一种可以参考这篇文章:http://www.cnblogs.com/guazi/p/6850988.html

    最终都是通过标黄代码那样来生成文件的。我们来看一下,就是MappedFile的构造方法:

        // 创建mappedfile文件
        public MapedFile(final String fileName, final int fileSize) throws IOException {
            this.fileName = fileName;
            this.fileSize = fileSize;
            this.file = new File(fileName);
            this.fileFromOffset = Long.parseLong(this.file.getName());
            boolean ok = false;
    
            ensureDirOK(this.file.getParent());
    
            try {
           // 这两个都是与文件对应的mappedfile对象属性变量 
    this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel(); this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0, fileSize);
           // 这两个是rocketmq系统的共享静态变量,用来标示虚拟内存使用情况和文件数量 TotalMapedVitualMemory.addAndGet(fileSize); TotalMapedFiles.incrementAndGet(); ok
    = true; } catch (FileNotFoundException e) { log.error("create file channel " + this.fileName + " Failed. ", e); throw e; } catch (IOException e) { log.error("map file " + this.fileName + " Failed. ", e); throw e; } finally { if (!ok && this.fileChannel != null) { this.fileChannel.close(); } } }
  • 相关阅读:
    HDU 3579 Hello Kiki 中国剩余定理
    DHU 1788 Chinese remainder theorem again 中国剩余定理
    初学--求解模线性方程组(中国余数定理)。
    山东第四届省赛: Boring Counting 线段树
    山东第四届省赛C题: A^X mod P
    福州大学oj 1752 A^B mod C ===>数论的基本功。位运用。五星*****
    HDU 1576 A/B 暴力也能过。扩展欧几里得
    POJ 1061 青蛙的约会 扩展欧几里德--解不定方程
    HDU 2669 Romantic 扩展欧几里德---->解不定方程
    南阳nyoj 56 阶乘因式分解(一)
  • 原文地址:https://www.cnblogs.com/guazi/p/6851319.html
Copyright © 2011-2022 走看看