Kafka 源代码分析之FileMessageSet
这里主要分析FileMessageSet类
这个类主要是管理log消息的内存对象和文件对象的类.源代码文件在log目录下.这个类被LogSegment类代理调用用来管理分片.
下面是完整代码.代码比较简单.就不做过多说明了.这个类是MessageSet抽象类的实现类.
class FileMessageSet private[kafka](@volatile var file: File,
private[log] val channel: FileChannel,
private[log] val start: Int,
private[log] val end: Int,
isSlice: Boolean) extends MessageSet with Logging { /* the size of the message set in bytes */
private val _size =
if(isSlice)
new AtomicInteger(end - start) // don't check the file size if this is just a slice view
else
new AtomicInteger(math.min(channel.size().toInt, end) - start) /* if this is not a slice, update the file pointer to the end of the file */
if (!isSlice)
/* set the file position to the last byte in the file */
channel.position(channel.size) /**
* Create a file message set with no slicing.
*/
def this(file: File, channel: FileChannel) =
this(file, channel, start = 0, end = Int.MaxValue, isSlice = false) /**
* Create a file message set with no slicing
*/
def this(file: File) =
this(file, Utils.openChannel(file, mutable = true)) /**
* Create a file message set with mutable option
*/
def this(file: File, mutable: Boolean) = this(file, Utils.openChannel(file, mutable)) /**
* Create a slice view of the file message set that begins and ends at the given byte offsets
*/
def this(file: File, channel: FileChannel, start: Int, end: Int) =
this(file, channel, start, end, isSlice = true) /**
* Return a message set which is a view into this set starting from the given position and with the given size limit.
*
* If the size is beyond the end of the file, the end will be based on the size of the file at the time of the read.
*
* If this message set is already sliced, the position will be taken relative to that slicing.
*
* @param position The start position to begin the read from
* @param size The number of bytes after the start position to include
*
* @return A sliced wrapper on this message set limited based on the given position and size
*/
def read(position: Int, size: Int): FileMessageSet = { //返回读取段对象
if(position < 0)
throw new IllegalArgumentException("Invalid position: " + position)
if(size < 0)
throw new IllegalArgumentException("Invalid size: " + size)
new FileMessageSet(file,
channel,
start = this.start + position,
end = math.min(this.start + position + size, sizeInBytes()))
} /**
* Search forward for the file position of the last offset that is greater than or equal to the target offset
* and return its physical position. If no such offsets are found, return null.
* @param targetOffset The offset to search for.
* @param startingPosition The starting position in the file to begin searching from.
*/
def searchFor(targetOffset: Long, startingPosition: Int): OffsetPosition = { //搜索读写点的方法
var position = startingPosition
val buffer = ByteBuffer.allocate(MessageSet.LogOverhead)
val size = sizeInBytes()
while(position + MessageSet.LogOverhead < size) {
buffer.rewind()
channel.read(buffer, position)
if(buffer.hasRemaining)
throw new IllegalStateException("Failed to read complete buffer for targetOffset %d startPosition %d in %s"
.format(targetOffset, startingPosition, file.getAbsolutePath))
buffer.rewind()
val offset = buffer.getLong()
if(offset >= targetOffset)
return OffsetPosition(offset, position)
val messageSize = buffer.getInt()
if(messageSize < Message.MessageOverhead)
throw new IllegalStateException("Invalid message size: " + messageSize)
position += MessageSet.LogOverhead + messageSize
}
null
} /**
* Write some of this set to the given channel.
* @param destChannel The channel to write to.
* @param writePosition The position in the message set to begin writing from.
* @param size The maximum number of bytes to write
* @return The number of bytes actually written.
*/
def writeTo(destChannel: GatheringByteChannel, writePosition: Long, size: Int): Int = { //主要写方法
// Ensure that the underlying size has not changed.
val newSize = math.min(channel.size().toInt, end) - start
if (newSize < _size.get()) {
throw new KafkaException("Size of FileMessageSet %s has been truncated during write: old size %d, new size %d"
.format(file.getAbsolutePath, _size.get(), newSize))
}
val bytesTransferred = channel.transferTo(start + writePosition, math.min(size, sizeInBytes), destChannel).toInt
trace("FileMessageSet " + file.getAbsolutePath + " : bytes transferred : " + bytesTransferred
+ " bytes requested for transfer : " + math.min(size, sizeInBytes))
bytesTransferred
} /**
* Get a shallow iterator over the messages in the set.
*/
override def iterator() = iterator(Int.MaxValue) /**
* Get an iterator over the messages in the set. We only do shallow iteration here.
* @param maxMessageSize A limit on allowable message size to avoid allocating unbounded memory.
* If we encounter a message larger than this we throw an InvalidMessageException.
* @return The iterator.
*/
def iterator(maxMessageSize: Int): Iterator[MessageAndOffset] = { //主要构造器.
new IteratorTemplate[MessageAndOffset] {
var location = start
val sizeOffsetBuffer = ByteBuffer.allocate(12) override def makeNext(): MessageAndOffset = {
if(location >= end)
return allDone() // read the size of the item
sizeOffsetBuffer.rewind()
channel.read(sizeOffsetBuffer, location)
if(sizeOffsetBuffer.hasRemaining)
return allDone() sizeOffsetBuffer.rewind()
val offset = sizeOffsetBuffer.getLong()
val size = sizeOffsetBuffer.getInt()
if(size < Message.MinHeaderSize)
return allDone()
if(size > maxMessageSize)
throw new InvalidMessageException("Message size exceeds the largest allowable message size (%d).".format(maxMessageSize)) // read the item itself
val buffer = ByteBuffer.allocate(size)
channel.read(buffer, location + 12)
if(buffer.hasRemaining)
return allDone()
buffer.rewind() // increment the location and return the item
location += size + 12
new MessageAndOffset(new Message(buffer), offset) //在这里做映射.同ByteBufferMessageSet里的实现方法类似.
}
}
} /**
* The number of bytes taken up by this file set
*/
def sizeInBytes(): Int = _size.get() /**
* Append these messages to the message set
*/
def append(messages: ByteBufferMessageSet) { //追加message的方法.被上层的append方法调用.
val written = messages.writeTo(channel, 0, messages.sizeInBytes)
_size.getAndAdd(written)
} /**
* Commit all written data to the physical disk
*/
def flush() = { //上层刷新方法的最终实现.
channel.force(true)
} /**
* Close this message set
*/
def close() {
flush()
channel.close()
} /**
* Delete this message set from the filesystem
* @return True iff this message set was deleted.
*/
def delete(): Boolean = { //上层delete函数的最终实现方法
Utils.swallow(channel.close()) //关闭内存数据
file.delete() //删除文件
} /**
* Truncate this file message set to the given size in bytes. Note that this API does no checking that the
* given size falls on a valid message boundary.
* @param targetSize The size to truncate to.
* @return The number of bytes truncated off
*/
def truncateTo(targetSize: Int): Int = {
val originalSize = sizeInBytes
if(targetSize > originalSize || targetSize < 0)
throw new KafkaException("Attempt to truncate log segment to " + targetSize + " bytes failed, " +
" size of this log segment is " + originalSize + " bytes.")
channel.truncate(targetSize)
channel.position(targetSize)
_size.set(targetSize)
originalSize - targetSize
} /**
* Read from the underlying file into the buffer starting at the given position
*/
def readInto(buffer: ByteBuffer, relativePosition: Int): ByteBuffer = {
channel.read(buffer, relativePosition + this.start)
buffer.flip()
buffer
} /**
* Rename the file that backs this message set
* @return true iff the rename was successful
*/
def renameTo(f: File): Boolean = {
val success = this.file.renameTo(f)
this.file = f
success
} } object LogFlushStats extends KafkaMetricsGroup {
val logFlushTimer = new KafkaTimer(newTimer("LogFlushRateAndTimeMs", TimeUnit.MILLISECONDS, TimeUnit.SECONDS))
}
Kafka 源代码分析之FileMessageSet的更多相关文章
- Kafka 源代码分析之LogManager
这里分析kafka 0.8.2的LogManager logmanager是kafka用来管理log文件的子系统.源代码文件在log目录下. 这里会逐步分析logmanager的源代码.首先看clas ...
- Kafka 源代码分析.
这里记录kafka源代码笔记.(代码版本是0.8.2.1) kafka的源代码如何下载.这里简单说一下. git clone https://git-wip-us.apache.org/repos/a ...
- Kafka 源代码分析之LogSegment
这里分析kafka LogSegment源代码 通过一步步分析LogManager,Log源代码之后就会发现,最终的log操作都在LogSegment上实现.LogSegment负责分片的读写恢复刷新 ...
- kafka 源代码分析之Message(v0.10)
这里主要更新一下kafka 0.10.0版本的message消息格式的变化. message 的格式在0.10.0的版本里发生了一些变化(相对于0.8.2.1的版本)这里把0.10.0的message ...
- Kafka 源代码分析之ByteBufferMessageSet
这里分析一下message的封装类ByteBufferMessageSet类 ByteBufferMessageSet类的源代码在源代码目录message目录下.这个类主要封装了message,mes ...
- Kafka 源代码分析之Log
这里分析Log对象本身的源代码. Log类是一个topic分区的基础类.一个topic分区的所有基本管理动作.都在这个对象里完成.类源代码文件为Log.scala.在源代码log目录下. Log类是L ...
- Kafka 源代码分析之Message
这里主要分析一下message的格式. 一条message的构成由以下部分组成 val CrcOffset = 0 //crc校验部分和字长 val CrcLength = 4 val MagicOf ...
- Kafka 源代码分析之MessageSet
这里分析MessageSet类 MessageSet是一个抽象类,定义了一条log的一些接口和常量,FileMessageSet就是MessageSet类的实现类.一条日志中存储的log完整格式如下 ...
- Kafka 源代码分析之log框架介绍
这里主要介绍log管理,读写相关的类的调用关系的介绍. 在围绕log的实际处理上.有很多层的封装和调用.这里主要介绍一下调用结构和顺序. 首先从LogManager开始. 调用关系简单如下:LogMa ...
随机推荐
- Vmware虚拟机中安装cnetOS7详细图解步骤
1.安装VMware 下载一个软件安装: .新建一个虚拟机 .引用安装包 4.启动新建的虚拟机 .安装CentOS7的步骤 配置系统语言: 配置系统时间: 配置系统键盘: 配置键盘切换的快捷键: 配置 ...
- 也许是目前实现最好的js模拟滚动插件
finger-mover 是一个集成 Fingerd(移动端以手指为单位的事件管理方案) 和 Moved(微型运动方案) 为一体的移动端动效平台,finger-mover 本身并不能为你做什么,但是附 ...
- 浅谈prototype和__proto__
讲prototype前先看一下对象的静态方法和实例方法. function Person () { }; Person.sayHello = function () { //定义一个静态方法 cons ...
- <<、>>、>>>移位操作
<<,有符号左移位,将运算数的二进制整体左移指定位数,低位用0补齐. int leftShift = 10; System.out.println("十进制:" + l ...
- hive的表的基本操作
环境简介 实验环境使用的是cloudera-quickstart-vm-5.0环境. 内容摘要 创建表 修改表名 修改表中的列名 添加列 删除列 替换列 正文 Alter Table 语句 上面所述的 ...
- Thread in Java
References: [1]. http://www.javaworld.com/article/2074481/java-concurrency/java-101--understanding-j ...
- java基础阅读卷1整理(待更新)
JAVA语言的一些简单摘要,分为11点 1.简单性2.面相对象3.网络技能(Network-Savvy)4.健壮性5.安全性 6.体系结构中立7.可移植性8.解释型9.高性能10.多线程11.多态性 ...
- MySql学习笔记(一) —— 正则表达式的使用
前面介绍利用一些关键字搭配相应的SQL语句进行数据库查找过滤,但随着过滤条件的复杂性的增加,where 子句本身的复杂性也会增加.这时我们就可以利用正则表达式来进行匹配查找. 1.基本字符匹配 ' o ...
- Git简略教程
Git使用教程 厂里大部分后端应用的版本控制工具为SVN,前端代码则更习惯于Git,好久不用Git有些生疏,复习一下,效率就是生命. 1.拉取远程分支到本地 git clone + 代码地址 + 分支 ...
- 深入理解C#中的String
关于C#中的类型 在C#中类型分为值类型和引用类型,引用类型和值类型都继承自System.Object类,几乎所有的引用类型都直接从System.Object继承,而值类型具体一点则继承System. ...