/** * Get the row at the given index. * * @param at the index * @return the row */ Row getRowAt(int at) { Row r = rows[at]; if (r == null) { if (firstOverflowPageId == 0) { r = readRow(data, offsets[at], columnCount); } else { if (rowRef != null) { r = rowRef.get(); if (r != null) { return r; } } PageStore store = index.getPageStore(); Data buff = store.createData(); int pageSize = store.getPageSize(); int offset = offsets[at]; buff.write(data.getBytes(), offset, pageSize - offset); int next = firstOverflowPageId; do { PageDataOverflow page = index.getPageOverflow(next); next = page.readInto(buff); } while (next != 0); overflowRowSize = pageSize + buff.length(); r = readRow(buff, 0, columnCount); } r.setKey(keys[at]); if (firstOverflowPageId != 0) { rowRef = new SoftReference<Row>(r); } else { rows[at] = r; memoryChange(true, r); } } return r; }
protected void remapChildren(int old) { if (firstOverflowPageId == 0) { return; } PageDataOverflow overflow = index.getPageOverflow(firstOverflowPageId); overflow.setParentPageId(getPos()); index.getPageStore().update(overflow); }
private void freeOverflow() { if (firstOverflowPageId != 0) { int next = firstOverflowPageId; do { PageDataOverflow page = index.getPageOverflow(next); page.free(); next = page.getNextOverflow(); } while (next != 0); } }
int addRowTry(Row row) { index.getPageStore().logUndo(this, data); int rowLength = getRowLength(row); int pageSize = index.getPageStore().getPageSize(); int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int keyOffsetPairLen = 2 + Data.getVarLongLen(row.getKey()); if (entryCount > 0 && last - rowLength < start + keyOffsetPairLen) { int x = findInsertionPoint(row.getKey()); if (entryCount > 1) { if (entryCount < 5) { // required, otherwise the index doesn't work correctly return entryCount / 2; } if (index.isSortedInsertMode()) { return x < 2 ? 1 : x > entryCount - 1 ? entryCount - 1 : x; } // split near the insertion point to better fill pages // split in half would be: // return entryCount / 2; int third = entryCount / 3; return x < third ? third : x >= 2 * third ? 2 * third : x; } return x; } index.getPageStore().logUndo(this, data); int x; if (entryCount == 0) { x = 0; } else { if (!optimizeUpdate) { readAllRows(); } x = findInsertionPoint(row.getKey()); } written = false; changeCount = index.getPageStore().getChangeCount(); last = x == 0 ? pageSize : offsets[x - 1]; int offset = last - rowLength; start += keyOffsetPairLen; offsets = insert(offsets, entryCount, x, offset); add(offsets, x + 1, entryCount + 1, -rowLength); keys = insert(keys, entryCount, x, row.getKey()); rows = insert(rows, entryCount, x, row); entryCount++; index.getPageStore().update(this); if (optimizeUpdate) { if (writtenData && offset >= start) { byte[] d = data.getBytes(); int dataStart = offsets[entryCount - 1] + rowLength; int dataEnd = offsets[x]; System.arraycopy(d, dataStart, d, dataStart - rowLength, dataEnd - dataStart + rowLength); data.setPos(dataEnd); for (int j = 0; j < columnCount; j++) { data.writeValue(row.getValue(j)); } } } if (offset < start) { writtenData = false; if (entryCount > 1) { DbException.throwInternalError(); } // need to write the overflow page id start += 4; int remaining = rowLength - (pageSize - start); // fix offset offset = start; offsets[x] = offset; int previous = getPos(); int dataOffset = pageSize; int page = index.getPageStore().allocatePage(); firstOverflowPageId = page; this.overflowRowSize = pageSize + rowLength; writeData(); // free up the space used by the row Row r = rows[0]; rowRef = new SoftReference<Row>(r); rows[0] = null; Data all = index.getPageStore().createData(); all.checkCapacity(data.length()); all.write(data.getBytes(), 0, data.length()); data.truncate(index.getPageStore().getPageSize()); do { int type, size, next; if (remaining <= pageSize - PageDataOverflow.START_LAST) { type = Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST; size = remaining; next = 0; } else { type = Page.TYPE_DATA_OVERFLOW; size = pageSize - PageDataOverflow.START_MORE; next = index.getPageStore().allocatePage(); } PageDataOverflow overflow = PageDataOverflow.create( index.getPageStore(), page, type, previous, next, all, dataOffset, size); index.getPageStore().update(overflow); dataOffset += size; remaining -= size; previous = page; page = next; } while (remaining > 0); } if (rowRef == null) { memoryChange(true, row); } else { memoryChange(true, null); } return -1; }