newPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getNextTID() - 1));
newPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getCurrentTID()));
    private RecordPos splitDataPage(DocumentImpl doc, RecordPos rec) {        if(currentDocument != null)            currentDocument.incSplitCount();        // check if a split is really required. A split is not required if all records        // following the split point are already links to other pages. In this case,        // the new record is just appended to a new page linked to the old one.        boolean requireSplit = false;        for (int pos = rec.offset; pos < rec.page.len;) {            short currentId = ByteConversion.byteToShort(rec.page.data, pos);            if(!ItemId.isLink(currentId)) {                requireSplit = true;                break;            }            pos += 10;        }        if(!requireSplit) {            LOG.debug("page " + rec.page.getPageNum() + ": no split required");            rec.offset = rec.page.len;            return rec;        }        NodeIndexListener idx = doc.getIndexListener();                // copy the old data up to the split point into a new array        int oldDataLen = rec.page.getPageHeader().getDataLength();        byte[] oldData = rec.page.data;        long oldPageNum = rec.page.getPageNum();        rec.page.data = new byte[fileHeader.getWorkSize()];        System.arraycopy(oldData, 0, rec.page.data, 0, rec.offset);                // the old rec.page now contains a copy of the data up to the split point        rec.page.len = rec.offset;        rec.page.setDirty(true);                // create a first split page        DOMPage firstSplitPage = new DOMPage();        DOMPage nextSplitPage = firstSplitPage;        nextSplitPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getCurrentTID()));        short tid, currentId, currentLen, realLen;        long backLink;        short splitRecordCount = 0;        LOG.debug("splitting " + rec.page.getPageNum() + " at " + rec.offset + ": new: "                + nextSplitPage.getPageNum() + "; next: " +                 rec.page.getPageHeader().getNextDataPage());                // start copying records from rec.offset to the new split pages        for (int pos = rec.offset; pos < oldDataLen; splitRecordCount++) {            // read the current id            currentId = ByteConversion.byteToShort(oldData, pos);            tid = ItemId.getId(currentId);            pos += 2;            if(ItemId.isLink(currentId)) {                /* This is already a link, so we just restore it into the old page */				if (rec.page.len + 10 > fileHeader.getWorkSize()) {					/* no room in the old page, append a new one */					DOMPage newPage = new DOMPage();					newPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getNextTID() - 1));                    newPage.getPageHeader().setPrevDataPage(rec.page.getPageNum());                    newPage.getPageHeader().setNextDataPage(rec.page.getPageHeader().getNextDataPage());                    LOG.debug("appending page after split: " + newPage.getPageNum());                    rec.page.getPageHeader().setNextDataPage(newPage.getPageNum());                    rec.page.getPageHeader().setDataLength(rec.page.len);                    rec.page.getPageHeader().setRecordCount(countRecordsInPage(rec.page));                    rec.page.setDirty(true);                    dataCache.add(rec.page);                    dataCache.add(newPage);                    rec.page = newPage;                    rec.page.len = 0;				}				// copy the link into the old page                ByteConversion.shortToByte(currentId,                        rec.page.data, rec.page.len);                rec.page.len += 2;				try {					System.arraycopy(oldData, pos, rec.page.data, rec.page.len, 8);				} catch(ArrayIndexOutOfBoundsException e) {					SanityCheck.TRACE("Failed to copy link record from " + pos + "; " + oldData.length +							"; to page " + rec.page.getPageNum() + "; " + rec.page.len + "; " + rec.page.data.length);				}                rec.page.len += 8;                pos += 8;                continue;            }            // read data length            currentLen = ByteConversion.byteToShort(oldData, pos);            pos += 2;            // if this is an overflow page, the real data length is always 8 byte            // for the page number of the overflow page            realLen = (currentLen == OVERFLOW ? 8 : currentLen);                        // check if we have room in the current split page            if(nextSplitPage.len + realLen + 12 > fileHeader.getWorkSize()) {                // not enough room in the split page: append a new page                DOMPage newPage = new DOMPage();                newPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getNextTID() - 1));                newPage.getPageHeader().setPrevDataPage(nextSplitPage.getPageNum());                LOG.debug("creating new split page: " + newPage.getPageNum());                nextSplitPage.getPageHeader().setNextDataPage(newPage.getPageNum());                nextSplitPage.getPageHeader().setDataLength(nextSplitPage.len);                nextSplitPage.getPageHeader().setRecordCount(splitRecordCount);                nextSplitPage.setDirty(true);                dataCache.add(nextSplitPage);                dataCache.add(newPage);                nextSplitPage = newPage;                splitRecordCount = 0;            }                        /* if the record has already been relocated, read the original storage             * address and update the link there.             */            if(ItemId.isRelocated(currentId)) {                backLink = ByteConversion.byteToLong(oldData, pos);                pos += 8;                RecordPos origRec = findRecord(backLink, false);                long forwardLink = StorageAddress.createPointer((int) nextSplitPage                        .getPageNum(), tid);                ByteConversion.longToByte(forwardLink, origRec.page.data, origRec.offset);                origRec.page.setDirty(true);                dataCache.add(origRec.page);            } else                backLink = StorageAddress.createPointer(                        (int) rec.page.getPageNum(), tid);                        // save the record to the split page:                        // set the relocated flag and save the item id            ByteConversion.shortToByte(ItemId.setIsRelocated(currentId),                    nextSplitPage.data, nextSplitPage.len);            nextSplitPage.len += 2;            //	save length field            ByteConversion.shortToByte(currentLen, nextSplitPage.data,                    nextSplitPage.len);            nextSplitPage.len += 2;            // save link to the original page            ByteConversion.longToByte(backLink, nextSplitPage.data,                    nextSplitPage.len);            nextSplitPage.len += 8;                        // now save the data            try {                 System.arraycopy(oldData, pos, nextSplitPage.data,                        nextSplitPage.len, realLen);            } catch (ArrayIndexOutOfBoundsException e) {                SanityCheck.TRACE("pos = " + pos + "; len = " + nextSplitPage.len + "; currentLen = " + realLen +                        "; tid = " + currentId + "; page = " + rec.page.getPageNum());                throw e;            }            nextSplitPage.len += realLen;            pos += realLen;            // report the split to the index listener. Pass it the old and the new storage address.            if(idx != null) {	            idx.nodeChanged(StorageAddress.createPointer((int) oldPageNum, tid), StorageAddress.createPointer(	                    (int) nextSplitPage.getPageNum(), tid));            }                        // save a link pointer in the original page if the record has not been            // relocated before.            if(!ItemId.isRelocated(currentId)) {                if(rec.page.len + 10 > fileHeader.getWorkSize()) {                    // the link doesn't fit into the old page. Append a new page                    DOMPage newPage = new DOMPage();                    newPage.getPageHeader().setNextTID((short)(rec.page.getPageHeader().getNextTID() - 1));                    newPage.getPageHeader().setPrevDataPage(rec.page.getPageNum());                    newPage.getPageHeader().setNextDataPage(rec.page.getPageHeader().getNextDataPage());                    LOG.debug("creating new page after split: " + newPage.getPageNum());                    rec.page.getPageHeader().setNextDataPage(newPage.getPageNum());                    rec.page.getPageHeader().setDataLength(rec.page.len);                    rec.page.getPageHeader().setRecordCount(countRecordsInPage(rec.page));                    rec.page.setDirty(true);                    dataCache.add(rec.page);                    dataCache.add(newPage);                    rec.page = newPage;                    rec.page.len = 0;                }                ByteConversion.shortToByte(ItemId.setIsLink(currentId),                    rec.page.data, rec.page.len);                rec.page.len += 2;                long forwardLink = StorageAddress.createPointer((int) nextSplitPage                    .getPageNum(), tid);                ByteConversion.longToByte(forwardLink, rec.page.data, rec.page.len);                rec.page.len += 8;            }        } // finished copying data                // link the split pages to the original page                if(nextSplitPage.len == 0) {            LOG.warn("page " + nextSplitPage.getPageNum() + " is empty. Remove it");            // if nothing has been copied to the last split page,            // remove it            dataCache.remove(nextSplitPage);            if(nextSplitPage == firstSplitPage)                firstSplitPage = null;            try {                unlinkPages(nextSplitPage.page);            } catch (IOException e) {                LOG.warn("Failed to remove empty split page: " + e.getMessage(), e);            }            nextSplitPage = null;        } else {	        nextSplitPage.getPageHeader().setDataLength(nextSplitPage.len);	        nextSplitPage.getPageHeader().setNextDataPage(	                rec.page.getPageHeader().getNextDataPage());	        nextSplitPage.getPageHeader().setRecordCount(splitRecordCount);	        nextSplitPage.setDirty(true);	        dataCache.add(nextSplitPage);	        firstSplitPage.getPageHeader().setPrevDataPage(rec.page.getPageNum());	        if(nextSplitPage != firstSplitPage) {	            firstSplitPage.setDirty(true);	            dataCache.add(firstSplitPage);	        }        }        long next = rec.page.getPageHeader().getNextDataPage();        if(-1 < next) {            DOMPage nextPage = getCurrentPage(next);            nextPage.getPageHeader().setPrevDataPage(nextSplitPage.getPageNum());            nextPage.setDirty(true);            dataCache.add(nextPage);        }        rec.page = getCurrentPage(rec.page.getPageNum());        if(firstSplitPage != null) {            rec.page.getPageHeader().setNextDataPage(firstSplitPage.getPageNum());        }        rec.page.getPageHeader().setDataLength(rec.page.len);        rec.page.getPageHeader().setRecordCount(countRecordsInPage(rec.page));        rec.offset = rec.page.len;        return rec;    }