标签:Golang
赛博坐牢之旅第一章第六节:接着上一节,补全heap_page剩下的函数。
开始坐牢
删除tuple
这个看起来…难度还没那么高,写一下试试吧。那就遍历tuple然后找rid呗。
func (h *heapPage) deleteTuple(rid recordID) error {
// TODO: some code goes here
for i, tuple := range h.Tuple {
if tuple.Rid == rid {
h.Tuple[i] = nil
h.Hdr.UsedSlots -= 1
return nil
}
}
return errors.New("the slot is invalid") //replace me
}
跑一下TestDeleteHeapPage,过。
确实有了思路之后写起来得心应手,接着往下看看。
别忘了还有个TestHeapPageDeleteTuple,跑一下。嗯?居然报错了。又是访问越界啊啊啊啊啊啊。
看看报错地方在哪里。仔细一看,tuple没判空……………………………tuple等于nil的话拿不到rid自然就会访问越界……………….补全一下
func (h *heapPage) deleteTuple(rid recordID) error {
// TODO: some code goes here
for i, tuple := range h.Tuple {
if tuple != nil && tuple.Rid == rid {
h.Tuple[i] = nil
h.Hdr.UsedSlots -= 1
return nil
}
}
return errors.New("the slot is invalid") //replace me
}
再test一下,过。
实验步骤
dirty
判断page是否为“脏页”和将page设置为“脏页”,那还得在page的结构里加个dirty。
type heapPage struct {
// TODO: some code goes here
Hdr Header
Tuple []*Tuple
Desc *TupleDesc
File *HeapFile
PageNo int
Dirty bool
}
这两个函数也没啥说的,挺简单的。
// Page method - return whether or not the page is dirty
func (h *heapPage) isDirty() bool {
// TODO: some code goes here
return h.Dirty //replace me
}
// Page method - mark the page as dirty
func (h *heapPage) setDirty(dirty bool) {
// TODO: some code goes here
h.Dirty = dirty
}
这个居然也有test,那就跑一下吧,过。
瞄了一眼下一个test,呵呵,又是序列化,看来赛博坐牢之旅还得继续。
实验步骤
返回对应的page
这个真的难吗?如难。
好吧仔细一看它真的有点难。因为注释就一句话:返回当前heap page所在的heapFile。
// Page method - return the corresponding HeapFile
// for this page.
func (p *heapPage) getFile() *DBFile {
// TODO: some code goes here
return nil //replace me
}
没其它提示了,那我们只能先看看DBFile的定义。
嗯…给的是一个接口,那么DBFile应该是包含heapfile的。那直接把heap page的file返回给接口不就好了…
func (p *heapPage) getFile() *DBFile {
// TODO: some code goes here
var dbFile DBFile = p.File
return &dbFile //replace me
}
没法test,因为GetPage还没写完,那就先….过!
实验步骤
又是序列化
序列化我是真的不熟。只能硬着头皮写了。先来看看要做些什么。
// Allocate a new bytes.Buffer and write the heap page to it. Returns an error
// if the write to the the buffer fails. You will likely want to call this from
// your [HeapFile.flushPage] method. You should write the page header, using
// the binary.Write method in LittleEndian order, followed by the tuples of the
// page, written using the Tuple.writeTo method.
func (h *heapPage) toBuffer() (*bytes.Buffer, error) {
// TODO: some code goes here
return nil, nil //replace me
}
// Read the contents of the HeapPage from the supplied buffer.
func (h *heapPage) initFromBuffer(buf *bytes.Buffer) error {
// TODO: some code goes here
return nil //replace me
}
序列化和反序列化在之前的tuple我们已经接触过了,那这里我们就直接开写呗。
老样子,先是写入缓冲区。感觉比tuple简单些,毕竟不用考虑不同的字段fields类型了。
func (h *heapPage) toBuffer() (*bytes.Buffer, error) {
// TODO: some code goes here
bytesBuffer := new(bytes.Buffer)
err := binary.Write(bytesBuffer, binary.LittleEndian, h.Hdr)
if err != nil {
return nil, err
}
for _, tuple := range h.Tuple {
if tuple != nil {
err := tuple.writeTo(bytesBuffer)
if err != nil {
return nil, err
}
}
}
return bytesBuffer, nil //replace me
}
接下来是读取缓冲区。读取的时候要注意范围,比如page可用102个插槽,表示的是从0-101下标的插槽都是可用的,所以TotalSlots要减一。
func (h *heapPage) initFromBuffer(buf *bytes.Buffer) error {
// TODO: some code goes here
err := binary.Read(buf, binary.LittleEndian, &h.Hdr)
if err != nil {
return err
}
for i := 0; i < int(h.Hdr.TotalSlots)-1; i++ {
tuple, err := readTupleFrom(buf, h.Desc)
if err != nil {
return err
}
h.Tuple[i] = tuple
}
return nil //replace me
}
run一下test,过。至此我们就完成了Exercise 3的全部内容,接下来就是完成Exercise 4咯。