int keyLeft = key.length;
int requireSpace;
int left;
int keyLength = 0;
DataPage last = null;
PageNumber firstOverflowPageNo = null;
for (int i = 0; i < overflows; i++) {
left = keyLeft;
if (left <= 0) break;
requireSpace = (left > freeSpace) ? freeSpace : left;
keyLength = (keyLeft >= freeSpace) ? freeSpace : keyLeft;
DataPage overflowPage = DataPage.newPage(page.btreeSpec, page.buffer, true, kContext, 0);
/********* add by leon *******
* Here a little trick is played to reduce the log record number.
* First we turn off the needLog switch to avoiding log individually.
* After done, we can log in batch.
*/
overflowPage.setLogInfo(txnId, false);
if (needLog) {
int pgno = overflowPage.getPageNumber().getPageNumber();
byte[] oldV = ByteTool.copyByteArray(overflowPage.getPage(), 0, BTreeSpec.PAGE_HEADER_SIZE);
byte[] newV = new byte[oldV.length];
System.arraycopy(oldV, 0, newV, 0, oldV.length);
System.arraycopy(ByteTool.intToBytes(4), 0, newV, BTreeSpec.OFF_FLAGS, 4);
System.arraycopy(ByteTool.shortToBytes((short) (overflowPage.upperBound - requireSpace)), 0, newV, BTreeSpec.OFF_UPPERBOUND, 2);
System.arraycopy(ByteTool.intToBytes(i == 0 ? page.pageNumber.getPageNumber() : last.pageNumber.getPageNumber()), 0, newV, BTreeSpec.OFF_PREVPAGE, 4);
if (ByteTool.compare(newV, 0, oldV, 0, oldV.length) != 0) {
BTreeReplLogRecord lr = new BTreeReplLogRecord(overflowPage.getPageNumber().getTreeId(), pgno, txnId, 0, oldV, newV, overflowPage.btreeSpec.btree.getType());
lr.log();
}
}
overflowPage.setOverflow();
overflowPage.setUpperBound((short) (overflowPage.upperBound - requireSpace));
if (i == 0) {
firstOverflowPageNo = overflowPage.pageNumber;
overflowPage.setPrevPage(page.pageNumber);
} else {
overflowPage.setPrevPage(last.pageNumber);
}
overflowPage.setLogInfo(txnId, needLog);
//set the previous page's next page
if (i > 0) last.setNextPage(overflowPage.pageNumber);
//add the new node
if (keyLength > 0) {
/******************* Add by leon, Sep 30 2001 *************/
if (needLog) {
int newPageNo = overflowPage.pageNumber.getPageNumber();
BTreeAddRemoveLogRecord logRec = new BTreeAddRemoveLogRecord(page.getPageNumber().getTreeId(), newPageNo, txnId, BTreeAddRemoveLogRecord.ADD_FLAG, overflowPage.upperBound, ByteTool.copyByteArray(key, keyStartPos, keyLength), page.btreeSpec.btree.getType());
logRec.log();
}
/*************************************************************/
System.arraycopy(key, keyStartPos, overflowPage.page, overflowPage.upperBound, keyLength);
keyStartPos += keyLength;
keyLeft -= keyLength;
}
//release the previoius overflow page. Dont' release nonOverflowpage
if (i > 0) page.buffer.releasePage(last.pageNumber.getTreeId(), last.pageNumber, true);
last = overflowPage;
}
//release the last overflow page
page.buffer.releasePage(last.pageNumber.getTreeId(), last.pageNumber, true);
//Since newing a page will set its next,previous page to be BTreeSpec.INVALID_PGNO,
//the last one has already been BTreeSpec.INVALID_PGNO and
//the overflow page chain has a end!
// add the new node to the current page
/***************** Add by leon,2001-9-27 14:56 ********************/
if (needLog) {
int pgno = page.pageNumber.getPageNumber();
byte[] newNode = ByteTool.copyByteArray(getHeader(), 0, BTreeSpec.NODE_HEADER_SIZE);
newNode = ByteTool.append(newNode, ByteTool.intToBytes(firstOverflowPageNo.getPageNumber()));
byte[] oldNode = ByteTool.copyByteArray(page.getPage(), nodeOffset, BTreeSpec.NODE_HEADER_SIZE + 4);
byte[] emptyNode = new byte[BTreeSpec.NODE_HEADER_SIZE + keySize];
if (ByteTool.compare(oldNode, 0, emptyNode, 0, BTreeSpec.NODE_HEADER_SIZE + keySize) == 0) {
BTreeAddRemoveLogRecord lr = new BTreeAddRemoveLogRecord(page.getPageNumber().getTreeId(), pgno, txnId, BTreeAddRemoveLogRecord.ADD_FLAG, nodeOffset, newNode, page.btreeSpec.btree.getType());
lr.log();
} else if (oldNode != newNode) {
BTreeReplLogRecord lr = new BTreeReplLogRecord(page.getPageNumber().getTreeId(), pgno, txnId, nodeOffset, oldNode, newNode, page.btreeSpec.btree.getType());
lr.log();
}
}
/******************************************************************/
System.arraycopy(this.getHeader(), 0, page.getPage(), nodeOffset, BTreeSpec.NODE_HEADER_SIZE);
// last pageNumber is the one we need here!!
System.arraycopy(ByteTool.intToBytes(firstOverflowPageNo.getPageNumber()), 0, page.getPage(), nodeOffset + BTreeSpec.NODE_HEADER_SIZE, 4);
}
}