SPage last = null;
while (last == null || last.children != null) {
last = findChildTail(last);
//TODO: do this lazily
TupleBatch batch = last.getValues();
places.add(new SearchResult(-batch.getTuples().size() -1, last, batch));
}
} else {
match = find(tuple, places);
if (match != null) {
if (mode != InsertMode.UPDATE) {
return match;
}
SearchResult last = places.getLast();
SPage page = last.page;
last.values.getTuples().set(last.index, tuple);
page.setValues(last.values);
return match;
}
}
List key = extractKey(tuple);
int level = 0;
if (mode != InsertMode.ORDERED) {
if (sizeHint > -1) {
level = Math.min(sizeHint, randomLevel());
} else {
level = randomLevel();
}
} else if (!places.isEmpty() && places.getLast().values.getTuples().size() == pageSize) {
int row = rowCount.get();
while (row != 0 && row%pageSize == 0) {
row = (row - pageSize + 1)/pageSize;
level++;
}
}
assert header.length == places.size();
if (level >= header.length) {
header = Arrays.copyOf(header, level + 1);
}
rowCount.addAndGet(1);
SPage page = null;
for (int i = 0; i <= level; i++) {
if (places.isEmpty()) {
SPage newHead = new SPage(this, false);
TupleBatch batch = newHead.getValues();
batch.getTuples().add(key);
newHead.setValues(batch);
newHead.children.add(page);
header[i] = newHead;
page = newHead;
} else {
SearchResult result = places.removeLast();
Object value = (i == 0 ? tuple : page);
page = insert(key, result, places.peekLast(), value, mode == InsertMode.ORDERED);
}
}
return null;