bbolt: open

签名
func Open(path string, mode os.FileMode, options *Options) (*DB, error)

  1. 打开文件
  2. lock, 调用syscall的flock
  3. 初始化或者读取文件元信息

每个page的初始元信息

type page struct {
	id       pgid
	flags    uint16
	count    uint16
	overflow uint32
	ptr      uintptr
}

ptr字段其实只是个站位的,ptr这个字段开始其实就是meta结构体的起始地址,ptr之前的是header信息

const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr))

// meta returns a pointer to the metadata section of the page.
func (p *page) meta() *meta {
	return (*meta)(unsafe.Pointer(&p.ptr))
}

可以看出pageHeaderSize就是拿ptr的起始地址作为长度的。
meta page的内存布局就是page heade --> meta。 page header的ptr地址就是meta的起始地址,两个数据结构通过ptr巧妙的连接在一起了。

meta:

type meta struct {
	magic    uint32
	version  uint32
	pageSize uint32
	flags    uint32
	root     bucket
	freelist pgid
	pgid     pgid
	txid     txid
	checksum uint64
}

init:
初始化四个page
0,1作为meta page, 为什么需要两个???
3,freelistpage
4,leafPage

读取:
读取文件千4k,检查meta是否合法:

// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
func (m *meta) validate() error {
	if m.magic != magic {
		return ErrInvalid
	} else if m.version != version {
		return ErrVersionMismatch
	} else if m.checksum != 0 && m.checksum != m.sum64() {
		return ErrChecksum
	}
	return nil
}

为什么是4k呢?因为page header和meta肯定不会超过4k

内存池:

	// Initialize page pool.
	db.pagePool = sync.Pool{
		New: func() interface{} {
			return make([]byte, db.pageSize)
		},
	}

loadFreelist:
这个freelist的作用是什么还要看写入过程发生了什么。我们可以从数据插入的过程来看,先假设走的是init流程,没有freelist,了解完freelist的用处以后再回过头来看这个

发布了96 篇原创文章 · 获赞 0 · 访问量 994

猜你喜欢

转载自blog.csdn.net/weixin_45594127/article/details/104076143