1.PageHeader
PageManager有一个成员变量FileHeader,FileHeader represents a file header. It is a 1:1 representation of the data
that appears in block 0 of a file.FileHeader主要是存储了一些数值:offset和blockid。这些数值是用一个也是RecordFile的第一个BLockIo对象进行存储的,所以它有一个BlockIo的引用。
先看其成员变量:
// offsets
private static final short O_MAGIC = 0; // short magic
private static final short O_LISTS = Magic.SZ_SHORT; // long[2*NLISTS]
private static final int O_ROOTS =
O_LISTS + (Magic.NLISTS * 2 * Magic.SZ_LONG);
// my block
private BlockIo block;
O_MAGIC表示FileHeader标示的位置:block.writeShort(O_MAGIC, Magic.FILE_HEADER)向0的位置写入
FileHeader的文件头。
O_LISTS标示LISTS的offset的位置,显然前面是short类型的变量,所以O_LISTS = Magic.SZ_SHORT
O_ROOTS = O_LISTS + (Magic.NLISTS * 2 * Magic.SZ_LONG) Magic.NLISTS等于5,即五个List:
short FREE_PAGE = 0;
short USED_PAGE = 1;
short TRANSLATION_PAGE = 2;
short FREELOGIDS_PAGE = 3;
short FREEPHYSIDS_PAGE = 4;
乘2则表示每隔List需要使用2个Magic.SZ_LONG长度,FIleHeader使用2个Magic.SZ_LONG长度的来记录当前list
中第一个和最后一个block的offset:
/**
* Returns the first block of the indicated list
*/
long getFirstOf(int list) {
return block.readLong(offsetOfFirst(list));
}
/**
* Sets the first block of the indicated list
*/
void setFirstOf(int list, long value) {
block.writeLong(offsetOfFirst(list), value);
}
上面的getFirstOf和setFirstOf中输入的参数int list是0~4的值,即上面的5中list的类型值
即getFirstOf和setFirstOf式获取和设置相应list第一个block顺序号的大小
而下面是设置最后一个block顺序号的大小。
/**
* Returns the last block of the indicated list
*/
long getLastOf(int list) {
return block.readLong(offsetOfLast(list));
}
/**
* Sets the last block of the indicated list
*/
void setLastOf(int list, long value) {
block.writeLong(offsetOfLast(list), value);
}
/** Returns the offset of the "first" block of the indicated list */
private short offsetOfFirst(int list) {
return (short) (O_LISTS + (2 * Magic.SZ_LONG * list));
}
/** Returns the offset of the "last" block of the indicated list */
private short offsetOfLast(int list) {
return (short) (offsetOfFirst(list) + Magic.SZ_LONG);
}
2.PageManager
PageManager管理5个LinkedList,每一个type有一个LinkedList,LinkedList里面的元素就是BlockIo对象。这些LinkedList构成了
RecordFile对象。一个PageManager只有一个FileHeader。
// our record file
private RecordFile file;
// header data
private FileHeader header;
private BlockIo headerBuf;
/**
* Creates a new page manager using the indicated record file.
*/
PageManager(RecordFile file) throws IOException {
this.file = file;
// check the file header. If the magic is 0, we assume a new
// file. Note that we hold on to the file header node.
headerBuf = file.get(0);
if (headerBuf.readShort(0) == 0)
header = new FileHeader(headerBuf, true);
else
header = new FileHeader(headerBuf, false);
}
PageHeader对BlockIo进行了封装,也就是说LinkedList里面元素实际上市PageHeader对象。但是这是为什么呢?
这个PageHeader主要是做什么的?而且这写是怎么关联起来的呢?下面在PageManager的allocate方法有几行代码
可能帮助理解:
buf = file.get(oldLast);
pageHdr = PageHeader.getView(buf);
pageHdr.setNext(retval);
file.release(oldLast, true);
每一个BlockIo都需要一个PageHeader,这点我真是不大理解,PageHeader,这个Page到底是什么?难道
每一个BlockIo都是一个Page?PageHeader的主要方法就是设置next和previous:
/** Returns the next block. */
long getNext() {
paranoiaMagicOk();
return block.readLong(O_NEXT);
}
/** Sets the next block. */
void setNext(long next) {
paranoiaMagicOk();
block.writeLong(O_NEXT, next);
}
/** Returns the previous block. */
long getPrev() {
paranoiaMagicOk();
return block.readLong(O_PREV);
}
/** Sets the previous block. */
void setPrev(long prev) {
paranoiaMagicOk();
block.writeLong(O_PREV, prev);
}
next和previous的id放在O_NEXT和O_PREV的位置。
3.PageHeader的作用
PageHeader类构造函数有一个参数BlockIo block,注释应为@param block The block that contains the page header
而不是@param block The block that contains the file header。
这基本可以确定,每一个BLockIo都有一个PageHeader,这些PageHeader构成一个LinkedList。
那么怎么得到这些LinkedList里面的对象呢?看一下PageManager这些方法就知道了:
/**
* Returns the page following the indicated block
*/
long getNext(long block) throws IOException {
try {
return PageHeader.getView(file.get(block)).getNext();
} finally {
file.release(block, false);
}
}
/**
* Returns the page before the indicated block
*/
long getPrev(long block) throws IOException {
try {
return PageHeader.getView(file.get(block)).getPrev();
} finally {
file.release(block, false);
}
}
/**
* Returns the first page on the indicated list.
*/
long getFirst(short type) throws IOException {
return header.getFirstOf(type);
}
/**
* Returns the last page on the indicated list.
*/
long getLast(short type) throws IOException {
return header.getLastOf(type);
}
其实一般不会这么直接获取,而是通过如下的代码进行的:
RecordFile f = new RecordFile(TestRecordFile.testFileName);
pm = new PageManager(f);
PageCursor curs = new PageCursor(pm, Magic.USED_PAGE);
long i = 1;
while (true) {
long cur = curs.next();
if (cur == 0)
break;
//对cur进行操作
}
pm.close();
f.close();