MINIBASE源代码阅读笔记之heapfile
Heapfile
用来管理heap file里的dir page们
成员
- _firstDirPageId:这个文件的第一个dir page
- _ftype:文件类型
- _file_deleted:删除的时候用的falg
- _fileName:文件名
方法
-
HeapFile:接收名字,如果是null就开个临时的heapfile(离开的时候会被destructor干掉),否则打开已有文件or创建新文件
- 先假设文件已经被干掉,设置filedeleted与_fileName
- 如果name是null,起一个临时文件名,否则用给的名字。(这里看到了古老的strdup……)
- 试图用DB->getfileentry获得第一个dir page并将得到的page id写进_firstDirPageId
- 如果失败,说明文件还不存在
- 用Buffer Manager创建一个新dir page到frame中
- 将这个创建了第一个dir page的file entry加入DB中
- 接着为这个已经在内存里的dir page初始化一个实体HFPage,设好id,将前后设为空,然后让Buffer manager unpin并指明它是dirty的
- 如果成功,说明文件已经存在,往下走
- 如果失败,说明文件还不存在
- 将暂设的_file_deleted设回去
- 完成之后保证:firstDirPageId指向这个file的第一个 dir page,fileName对应系统里实际存在的文件,此时还没pin过任何data page
-
~HeapFile:执行前需要保证所有page都没有被pin,所有private member都是有效的
- 首先删除_fileName
- 如果是temp file,用deleteFile删掉这个临时文件
- 如果不是,而且这时有多个USER,需要对第一个dirPage加锁然后unpin
-
getRecCnt:返回整个文件里有多少record
- 遍历每个dir page(查看前要先pin),把里面每个data page的info里的recct累加进answer
- 每个dir page遍历之后要转换到下一个page,并且unpin
-
insertRecord:接收一个record的指针,内容长度,用来写分配好的rid的参数
- 遍历每个dir page,寻找其中有足够空间(dpinfo.availspace>=recLen)的data page
- 如果当前dir page里已有的data page都不够放:
- 目前的dir page还能够增加新的data page,创建新的data page(_newDataPage),将新的data page插入当前dir page(调用dir page的insertRecord),再在这个新的data page插入record
- 目前的dir page已满,去找下一个dir page(。。。有点蠢?不过record是尽量放到前面的dir page里好点)
- 如果有下一个dir page,unpin现在的dir page,pin下一个dir page,回到outer loop继续找
- 如果已经没有下一个dir page了,怒再创建一个dir page,先buffer manager的newPage,各种初始化,设current dir page的下一个dir page是这个新的dir page(接到链表尾巴),unpin现在的dir page,current dir page轮换到这个新的,然后回到outer loop,这下空间总够了。。
- 找到了可以放的data page之后,pin之,一通检查,然后将record插进去,将它的recct++,更新availspace
- unpin datapage,注意要说明它是dirty的
- 更新dir page里作为record的dpinfo(前面更新的是data page自带的dpinfo)
-
deleteRecord:接收rid,删除record
- 先把关联的dir page、data page的指针、id和info都拿到手
- 在data page里删掉record,修改recct
- 如果这个时候data page空了(recct==0),free掉data page,在dir page里删掉对应的record
- 如果这个时候dir page也跟着空了(getFirstRecord没返回OK),也删掉这个dir page
- 要检查有没有前一个dir page,有的话绕过去
- 再检查有没有后一个dir page,有的话绕过去
- 检查完之后unpin这个dir page,然后free掉
- 如果没啥空的,该unpin就unpin,然后返回
-
updateRecord:接收rid,新record的指针和长度,负责把新的record覆盖掉rid所指的record
- 先找data page,找到了去找record,如果长度不和原来一样,报错就跑(= =b)
- 用memcpy修改,unpin掉data page和dir page,返回
-
getRecord:接收rid,指针,长度,读取指定长度的数据写进指针里
- 调用_findDataPage找有这个rid的data page
- 如果找不到,返回状态码
- 如果找得到,再对这个data page调用getRecord,将record写进来,unpin掉用过的page,返回
-
openScan:发起scan
- new一个scan,传进this。。。跑人。。
-
deleteFile:将这个file从database删除
- 如果_file_deleted这个flag是true,说明已经删掉了,报错
- 遍历所有dirPage,删除它们reference的所有data Page(没删完之前要pin住dir page)
- 遍历dirPage的每一个record,里面存有这个file里每一个data page的id,用buffer manager free掉每一个data page(deallocate硬盘空间)
- 获取它后面的dir Page(如果有),删除它自己。如果有下一个dir Page,让buffer manager pin住再进入下一个pass
- 最后删掉file_entry和header page,搞定
- _newDatapage:接收DataPageInfo来分配一个新的data page,注意这个只是用来分配新page的,需要在其他地方将这个新的data page加入directory中
- 先让buffer manager newPage,这样可以进到buffer pool里
- 设置好这个新page的信息(前后为空,pageid设好)
- 设置对应的dpinfo
- _findDatapage:给getRecord和upadateRecord用的,接收rid,将找到的reocrd的位置对应记录在dirPage和dataPage的id与指针参数里,datapage在dir page里的rid,也就是根据rid找它对应的datapa page
- 遍历每个dir page的每个data page,用returnRecord确定在不在data page里,找啊找直到找到为止,把对应的参数写好,返回
- 查看之前要pin,看完要unpin
- 如果找不到,最后面把指针设为NULL,各种id设为INVALID_PAGE,返回
DataPageInfo
描述data page的状况,这是dir page里的record
- availspace: 还剩多少可用空间
- recct: 里面有多少record
- PageId