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();