MINIBASE源代码阅读笔记之heapfile

Heapfile

用来管理heap file里的dir page们

成员

  • _firstDirPageId:这个文件的第一个dir page
  • _ftype:文件类型
  • _file_deleted:删除的时候用的falg
  • _fileName:文件名

方法

  • HeapFile:接收名字,如果是null就开个临时的heapfile(离开的时候会被destructor干掉),否则打开已有文件or创建新文件

    1. 先假设文件已经被干掉,设置filedeleted与_fileName
    2. 如果name是null,起一个临时文件名,否则用给的名字。(这里看到了古老的strdup……)
    3. 试图用DB->getfileentry获得第一个dir page并将得到的page id写进_firstDirPageId
      1. 如果失败,说明文件还不存在
        1. 用Buffer Manager创建一个新dir page到frame中
        2. 将这个创建了第一个dir page的file entry加入DB中
        3. 接着为这个已经在内存里的dir page初始化一个实体HFPage,设好id,将前后设为空,然后让Buffer manager unpin并指明它是dirty的
      2. 如果成功,说明文件已经存在,往下走
    4. 将暂设的_file_deleted设回去
    5. 完成之后保证:firstDirPageId指向这个file的第一个 dir page,fileName对应系统里实际存在的文件,此时还没pin过任何data page
  • ~HeapFile:执行前需要保证所有page都没有被pin,所有private member都是有效的

    1. 首先删除_fileName
    2. 如果是temp file,用deleteFile删掉这个临时文件
    3. 如果不是,而且这时有多个USER,需要对第一个dirPage加锁然后unpin
  • getRecCnt:返回整个文件里有多少record

    1. 遍历每个dir page(查看前要先pin),把里面每个data page的info里的recct累加进answer
    2. 每个dir page遍历之后要转换到下一个page,并且unpin
  • insertRecord:接收一个record的指针,内容长度,用来写分配好的rid的参数

    1. 遍历每个dir page,寻找其中有足够空间(dpinfo.availspace>=recLen)的data page
    2. 如果当前dir page里已有的data page都不够放:
      1. 目前的dir page还能够增加新的data page,创建新的data page(_newDataPage),将新的data page插入当前dir page(调用dir page的insertRecord),再在这个新的data page插入record
      2. 目前的dir page已满,去找下一个dir page(。。。有点蠢?不过record是尽量放到前面的dir page里好点)
      3. 如果有下一个dir page,unpin现在的dir page,pin下一个dir page,回到outer loop继续找
      4. 如果已经没有下一个dir page了,怒再创建一个dir page,先buffer manager的newPage,各种初始化,设current dir page的下一个dir page是这个新的dir page(接到链表尾巴),unpin现在的dir page,current dir page轮换到这个新的,然后回到outer loop,这下空间总够了。。
    3. 找到了可以放的data page之后,pin之,一通检查,然后将record插进去,将它的recct++,更新availspace
    4. unpin datapage,注意要说明它是dirty的
    5. 更新dir page里作为record的dpinfo(前面更新的是data page自带的dpinfo)
  • deleteRecord:接收rid,删除record

    1. 先把关联的dir page、data page的指针、id和info都拿到手
    2. 在data page里删掉record,修改recct
    3. 如果这个时候data page空了(recct==0),free掉data page,在dir page里删掉对应的record
    4. 如果这个时候dir page也跟着空了(getFirstRecord没返回OK),也删掉这个dir page
      1. 要检查有没有前一个dir page,有的话绕过去
      2. 再检查有没有后一个dir page,有的话绕过去
      3. 检查完之后unpin这个dir page,然后free掉
    5. 如果没啥空的,该unpin就unpin,然后返回
  • updateRecord:接收rid,新record的指针和长度,负责把新的record覆盖掉rid所指的record

    1. 先找data page,找到了去找record,如果长度不和原来一样,报错就跑(= =b)
    2. 用memcpy修改,unpin掉data page和dir page,返回
  • getRecord:接收rid,指针,长度,读取指定长度的数据写进指针里

    1. 调用_findDataPage找有这个rid的data page
    2. 如果找不到,返回状态码
    3. 如果找得到,再对这个data page调用getRecord,将record写进来,unpin掉用过的page,返回
  • openScan:发起scan

    1. new一个scan,传进this。。。跑人。。
  • deleteFile:将这个file从database删除

    1. 如果_file_deleted这个flag是true,说明已经删掉了,报错
    2. 遍历所有dirPage,删除它们reference的所有data Page(没删完之前要pin住dir page)
      1. 遍历dirPage的每一个record,里面存有这个file里每一个data page的id,用buffer manager free掉每一个data page(deallocate硬盘空间)
      2. 获取它后面的dir Page(如果有),删除它自己。如果有下一个dir Page,让buffer manager pin住再进入下一个pass
    3. 最后删掉file_entry和header page,搞定
  • _newDatapage:接收DataPageInfo来分配一个新的data page,注意这个只是用来分配新page的,需要在其他地方将这个新的data page加入directory中
    1. 先让buffer manager newPage,这样可以进到buffer pool里
    2. 设置好这个新page的信息(前后为空,pageid设好)
    3. 设置对应的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
posted @ 2014-04-17 22:34  Joyee  阅读(649)  评论(0编辑  收藏  举报