etcd中的环形队列inflights

本文详细解析了inflights结构体,它是用于记录节点已发出但未收到响应的MsgApp消息的重要数据结构。文章深入介绍了inflights的字段含义、创建、添加、扩容、释放等操作,并解释了其作为环形数组的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

inflights结构体在progress.go文件中,主要用于记录当前节点已发出未收到的响应的MsgApp消息,具体实现如下

type inflights struct {
	// the starting index in the buffer
	start int   //记录第一条MsgApp消息的下标
	// number of inflights in the buffer
	count int   //记录MsgApp消息的个数

	// the size of the buffer
	size int   //当前inflights实例中记录的MsgApp消息个数的上限(最大长度)。

	// buffer contains the index of the last entry
	// inside one message.
	buffer []uint64   //用来记录MsgApp消息相关信息的数组,其中记录的是MsgApp消息中最后一条Entry记录的索引值,被当成环形数组使用
}

func newInflights(size int) *inflights {
	return &inflights{
		size: size,
	}
}

// add adds an inflight into inflights
//用来记录发送出去的MsgApp消息(一个一个的递增)
func (in *inflights) add(inflight uint64) {
	if in.full() {  //检测当前buffer数组是否已经被填充满了
		panic("cannot add into a full inflights")
	}
	next := in.start + in.count    //获取新增消息的下标
	size := in.size
	if next >= size {   //环形队列
		next -= size
	}
	if next >= len(in.buffer) {  //初始化的buffer数组较短,随着使用会不断进行扩容(2倍),其扩容的上限为size
		in.growBuf()
	}
	in.buffer[next] = inflight   //在next位置记录消息中最后一条Entry记录的索引值
	in.count++   //递增count字段
}

// grow the inflight buffer by doubling up to inflights.size. We grow on demand
// instead of preallocating to inflights.size to handle systems which have
// thousands of Raft groups per process.
func (in *inflights) growBuf() {
	newSize := len(in.buffer) * 2
	if newSize == 0 {
		newSize = 1
	} else if newSize > in.size {
		newSize = in.size
	}
	newBuffer := make([]uint64, newSize)
	copy(newBuffer, in.buffer)
	in.buffer = newBuffer
}

// freeTo frees the inflights smaller or equal to the given `to` flight.
//将指定消息及其之前的消息全部清空,释放inflights空间,让后面的消息继续发送。
func (in *inflights) freeTo(to uint64) {
	if in.count == 0 || to < in.buffer[in.start] {  //边界检测
		// out of the left side of the window
		return
	}

	idx := in.start
	var i int
	for i = 0; i < in.count; i++ {
		if to < in.buffer[idx] { // found the first large inflight
			break
		}

		// increase index and maybe rotate
		size := in.size
		if idx++; idx >= size {
			idx -= size
		}
	}
	// free i inflights and set new start index
	in.count -= i
	in.start = idx
	if in.count == 0 {
		// inflights is empty, reset the start index so that we don't grow the
		// buffer unnecessarily.
		in.start = 0
	}
}

func (in *inflights) freeFirstOne() { in.freeTo(in.buffer[in.start]) }

// full returns true if the inflights is full.
func (in *inflights) full() bool {
	return in.count == in.size
}

// resets frees all inflights.
func (in *inflights) reset() {
	in.count = 0
	in.start = 0
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值