private void removeRow(int i) { index.getPageStore().logUndo(this, data); written = false; changeCount = index.getPageStore().getChangeCount(); if (!optimizeUpdate) { readAllRows(); } Row r = getRowAt(i); if (r != null) { memoryChange(false, r); } entryCount--; if (entryCount < 0) { DbException.throwInternalError(); } if (firstOverflowPageId != 0) { start -= 4; freeOverflow(); firstOverflowPageId = 0; overflowRowSize = 0; rowRef = null; } int keyOffsetPairLen = 2 + Data.getVarLongLen(keys[i]); int startNext = i > 0 ? offsets[i - 1] : index.getPageStore().getPageSize(); int rowLength = startNext - offsets[i]; if (optimizeUpdate) { if (writtenData) { byte[] d = data.getBytes(); int dataStart = offsets[entryCount]; System.arraycopy(d, dataStart, d, dataStart + rowLength, offsets[i] - dataStart); Arrays.fill(d, dataStart, dataStart + rowLength, (byte) 0); } } else { int clearStart = offsets[entryCount]; Arrays.fill(data.getBytes(), clearStart, clearStart + rowLength, (byte) 0); } start -= keyOffsetPairLen; offsets = remove(offsets, entryCount + 1, i); add(offsets, i, entryCount, rowLength); keys = remove(keys, entryCount + 1, i); rows = remove(rows, entryCount + 1, i); }
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; }