博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
大众点评Cat源码分析(三)——数据文件(MessageTree)读写磁盘详细逻辑
阅读量:6071 次
发布时间:2019-06-20

本文共 2206 字,大约阅读时间需要 7 分钟。

hot3.png

一、MessageTree数据文件存储逻辑图

输入图片说明

二、MessageTree写入磁盘的逻辑

代码如下:

/**	 *  m_indexFile \data\appdatas\cat\bucket\dump\20171204\10\cat-10.15.83.181-10.15.83.181.idx	 * @param block	 * @throws IOException	 * @description 	 * 1、获取block块内树的棵数,遍历每一棵树	 * 2、按照 6B(前4B写入整个block在dataFile中的其实位置,后2B写每一棵树在block内的偏移)写索引文件	 * 3、将block的长度,作为一个int类型写入到dataFile	 * 4、将block的data,接着写入dataFile	 */	public synchronized void writeBlock(MessageBlock block) throws IOException {		int len = block.getBlockSize();//块内MessageTree的个数		byte[] data = block.getData();//块内所有树的字节		int blockSize = 0;		//遍历块内每一个树,对应的index,和树的size(字节)		for (int i = 0; i < len; i++) {			int seq = block.getIndex(i);			int size = block.getSize(i);			m_indexFile.seek(seq * 6L);//取6位,前4位是messageId的最后一个字段的index,后面是这个消息对应的size的偏移量			m_indexFile.writeInt(m_blockAddress);//这几棵数的块内地址是一样的,但是,索引地址不一样			m_indexFile.writeShort(blockSize);//块内的偏移量			blockSize += size;//block的总大小,字节数		}		m_dataFile.writeInt(data.length);//数据偏移的前面四个字节,是数据长度,接下来才是消息本身		m_dataFile.write(data);		m_blockAddress += data.length + 4;//偏移量+4个字节	}

三、MessageTree从磁盘中读出的逻辑

代码如下:

/**	 * m_dataFile  \data\appdatas\cat\bucket\dump\20171204\09\cat-10.15.83.181-10.15.83.181	 * @param index	 * @return	 * @throws IOException	 * 读逻辑:	 *    1、根据index找到索引文件的起始位置	 *    2、读6B,前4B是数据文件的数据库的起始位置,后2B是MessageTree块内的偏移地址	 *    3、找到数据文件块的起始地址,读取一个int类型数据,这个是整个数据块的长度	 *    4、接着读取这么长的数据,即为整个数据块,对应MessageBlock	 *    5、在数据块内,skip到MessageTree的块内地址	 *    6、读取一个整型,这个整型即为MessageTree的长度,接着读出这棵消息树	 */	public byte[] readMessage(int index) throws IOException {		int blockAddress = 0;		int blockOffset = 0;		byte[] buf;		m_indexFile.seek(index * 6L);		blockAddress = m_indexFile.readInt();		blockOffset = m_indexFile.readShort() & 0xFFFF;		m_dataFile.seek(blockAddress);		buf = new byte[m_dataFile.readInt()];		m_dataFile.readFully(buf);		ByteArrayInputStream bais = new ByteArrayInputStream(buf);		DataInputStream in = new DataInputStream(new GZIPInputStream(bais));		try {			in.skip(blockOffset);			int len = in.readInt();			byte[] data = new byte[len];			in.readFully(data);			return data;		} finally {			try {				in.close();			} catch (Exception e) {				// ignore it			}		}	}

转载于:https://my.oschina.net/liangxiao/blog/1584375

你可能感兴趣的文章
默认虚拟主机设置
查看>>
七周五次课(1月26日)
查看>>
Linux系统一些系统查看指令
查看>>
php中的短标签 太坑人了
查看>>
[译] 可维护的 ETL:使管道更容易支持和扩展的技巧
查看>>
### 继承 ###
查看>>
数组扩展方法之求和
查看>>
astah-professional-7_2_0安装
查看>>
函数是对象-有属性有方法
查看>>
uva 10107 - What is the Median?
查看>>
Linux下基本栈溢出攻击【转】
查看>>
c# 连等算式都在做什么
查看>>
使用c:forEach 控制5个换行
查看>>
java web轻量级开发面试教程摘录,java web面试技巧汇总,如何准备Spring MVC方面的面试...
查看>>
根据调试工具看Vue源码之组件通信(一)
查看>>
Thrift RPC 系列教程(5)—— 接口设计篇:struct & enum设计
查看>>
斯坦福-随机图模型-week1.5
查看>>
灵活的运用Model类
查看>>
hadoop 之分布式安装
查看>>
使用ansible工具部署ceph
查看>>