Object[] keys, Object[] values, PageReference[] children, long totalCount, int memory) { Page p = new Page(map, version); p.memory = IN_MEMORY; } else if (memory == 0) { p.recalculateMemory(); } else { p.addMemory(memory);
@SuppressWarnings("unchecked") private K getMinMax(Page p, K key, boolean min, boolean excluding) { if (p.isLeaf()) { int x = p.binarySearch(key); if (x < 0) { x = -x - (min ? 2 : 1); x += min ? -1 : 1; if (x < 0 || x >= p.getKeyCount()) { return null; return (K) p.getKey(x); int x = p.binarySearch(key); if (x < 0) { x = -x - 1; return null; K k = getMinMax(p.getChildPage(x), key, min, excluding); if (k != null) { return k;
int index = p.binarySearch(key); if (p.isLeaf()) { if (index < 0) { index = -index - 1; p.insertLeaf(index, key, value); return null; return p.setValue(index, value); index++; Page c = p.getChildPage(index).copy(writeVersion); if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 1) { int at = c.getKeyCount() / 2; Object k = c.getKey(at); Page split = c.split(at); p.setChild(index, split); p.insertNode(index, k, c); p.setChild(index, c); return result;
private static void move(Page source, Page target, int sourceIndex) { Object k = source.getKey(sourceIndex); if (source.isLeaf()) { Object v = source.getValue(sourceIndex); target.insertLeaf(0, k, v); } else { Page c = source.getChildPage(sourceIndex); target.insertNode(0, k, c); } source.remove(sourceIndex); }
PageChildren(Page p) { this.pos = p.getPos(); int count = p.getRawChildPageCount(); this.children = new long[count]; for (int i = 0; i < count; i++) { children[i] = p.getChildPagePos(i); } }
/** * Create a copy of this page. * * @param version the new version * @return a page with the given version */ public Page copy(long version) { Page newPage = create(map, version, keys, values, children, totalCount, memory); // mark the old as deleted removePage(); newPage.cachedCompare = cachedCompare; return newPage; }
@Override protected synchronized Object remove(Page p, long writeVersion, Object key) { Object result = null; if (p.isLeaf()) { for (int i = 0; i < p.getKeyCount(); i++) { if (keyType.equals(p.getKey(i), key)) { result = p.getValue(i); p.remove(i); break; for (int i = 0; i < p.getKeyCount(); i++) { if (contains(p, i, key)) { Page cOld = p.getChildPage(i); Page c = cOld.copy(writeVersion); long oldSize = c.getTotalCount(); result = remove(c, writeVersion, key); p.setChild(i, c); if (oldSize == c.getTotalCount()) { continue; if (c.getTotalCount() == 0) { p.remove(i); if (p.getKeyCount() == 0) { c.removePage(); Object oldBounds = p.getKey(i); if (!keyType.isInside(key, oldBounds)) { p.setKey(i, getBounds(c));
int index = p.binarySearch(key); Object result = null; if (p.isLeaf()) { if (index >= 0) { result = p.getValue(index); p.remove(index); index++; Page cOld = p.getChildPage(index); Page c = cOld.copy(writeVersion); result = remove(c, writeVersion, key); if (result == null || c.getTotalCount() != 0) { p.setChild(index, c); } else { if (p.getKeyCount() == 0) { p.setChild(index, c); c.removePage(); } else { p.remove(index);
private Page copy(Page source, CursorPos parent) { Page target = Page.create(this, writeVersion, source); if (source.isLeaf()) { Page child = target; for (CursorPos p = parent; p != null; p = p.parent) { p.page.setChild(p.index, child); p.page = p.page.copy(writeVersion); child = p.page; if (p.parent == null) { target.setChild(i, null); long p = source.getChildPagePos(i); if (p != 0) { copy(source.getChildPage(i), pos);
private int rewrite(Page p, Set<Integer> set) { if (p.isLeaf()) { long pos = p.getPos(); int chunkId = DataUtils.getPageChunkId(pos); if (!set.contains(chunkId)) { return 0; if (p.getKeyCount() > 0) { @SuppressWarnings("unchecked") K key = (K) p.getKey(0); V value = get(key); if (value != null) { long childPos = p.getChildPagePos(i); if (childPos != 0 && DataUtils.getPageType(childPos) == DataUtils.PAGE_TYPE_LEAF) { writtenPageCount += rewrite(p.getChildPage(i), set); long pos = p.getPos(); int chunkId = DataUtils.getPageChunkId(pos); if (set.contains(chunkId)) { while (!p2.isLeaf()) { p2 = p2.getChildPage(0); K key = (K) p2.getKey(0); V value = get(key); if (value != null) {
private void add(Page p, long writeVersion, Object key, Object value) { if (p.isLeaf()) { p.insertLeaf(p.getKeyCount(), key, value); return; for (int i = 0; i < p.getKeyCount(); i++) { if (contains(p, i, key)) { index = i; for (int i = 0; i < p.getKeyCount(); i++) { Object k = p.getKey(i); float areaIncrease = keyType.getAreaIncrease(k, key); if (areaIncrease < min) { Page c = p.getChildPage(index).copy(writeVersion); if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 4) { p.setKey(index, getBounds(c)); p.setChild(index, c); p.insertNode(index, getBounds(split), split); Object bounds = p.getKey(index); keyType.increaseBounds(bounds, key); p.setKey(index, bounds); p.setChild(index, c);
if (p.isLeaf()) { for (int i = 0; i < p.getKeyCount(); i++) { if (keyType.equals(p.getKey(i), key)) { p.setKey(i, key); return p.setValue(i, value); for (int i = 0; i < p.getKeyCount(); i++) { if (contains(p, i, key)) { Page c = p.getChildPage(i); if (get(c, key) != null) { c = c.copy(writeVersion); Object result = set(c, writeVersion, key, value); p.setChild(i, c); return result;
/** * Split the root page if necessary. * * @param p the page * @param writeVersion the write version * @return the new sibling */ protected Page splitRootIfNeeded(Page p, long writeVersion) { if (p.getMemory() <= store.getPageSplitSize() || p.getKeyCount() <= 1) { return p; } int at = p.getKeyCount() / 2; long totalCount = p.getTotalCount(); Object k = p.getKey(at); Page split = p.split(at); Object[] keys = { k }; Page.PageReference[] children = { new Page.PageReference(p, p.getPos(), p.getTotalCount()), new Page.PageReference(split, split.getPos(), split.getTotalCount()), }; p = Page.create(this, writeVersion, keys, null, children, totalCount, 0); return p; }
/** * Get the value for the given key, or null if not found. * * @param p the page * @param key the key * @return the value or null */ protected Object binarySearch(Page p, Object key) { int x = p.binarySearch(key); if (!p.isLeaf()) { if (x < 0) { x = -x - 1; } else { x++; } p = p.getChildPage(x); return binarySearch(p, key); } if (x >= 0) { return p.getValue(x); } return null; }
long offset = 0; while (true) { int x = p.binarySearch(key); if (p.isLeaf()) { if (x < 0) { return -offset + x; offset += p.getCounts(i); p = p.getChildPage(x);
/** * Remove a key-value pair, if the key exists. * * @param key the key (may not be null) * @return the old value if the key existed, or null otherwise */ @Override @SuppressWarnings("unchecked") public V remove(Object key) { beforeWrite(); V result = get(key); if (result == null) { return null; } long v = writeVersion; synchronized (this) { Page p = root.copy(v); result = (V) remove(p, v, key); if (!p.isLeaf() && p.getTotalCount() == 0) { p.removePage(); p = Page.createEmpty(this, p.getVersion()); } newRoot(p); } return result; }
private synchronized Object putOrAdd(SpatialKey key, V value, boolean alwaysAdd) { beforeWrite(); long v = writeVersion; Page p = root.copy(v); Object result; if (alwaysAdd || get(key) == null) { if (p.getMemory() > store.getPageSplitSize() && p.getKeyCount() > 3) { long totalCount = p.getTotalCount(); Page split = split(p, v); Object k1 = getBounds(p); Object[] keys = { k1, k2 }; Page.PageReference[] children = { new Page.PageReference(p, p.getPos(), p.getTotalCount()), new Page.PageReference(split, split.getPos(), split.getTotalCount()), new Page.PageReference(null, 0, 0) }; p = Page.create(this, v, keys, null, children,
/** * Fetch the next entry that is equal or larger than the given key, starting * from the given page. This method retains the stack. * * @param p the page to start * @param from the key to search */ private void min(Page p, K from) { while (true) { if (p.isLeaf()) { int x = from == null ? 0 : p.binarySearch(from); if (x < 0) { x = -x - 1; } pos = new CursorPos(p, x, pos); break; } int x = from == null ? -1 : p.binarySearch(from); if (x < 0) { x = -x - 1; } else { x++; } pos = new CursorPos(p, x + 1, pos); p = p.getChildPage(x); } }
private void recalculateMemory() { int mem = DataUtils.PAGE_MEMORY; DataType keyType = map.getKeyType(); for (Object key : keys) { mem += keyType.getMemory(key); } if (this.isLeaf()) { DataType valueType = map.getValueType(); for (int i = 0; i < keys.length; i++) { mem += valueType.getMemory(values[i]); } } else { mem += this.getRawChildPageCount() * DataUtils.PAGE_MEMORY_CHILD; } addMemory(mem - memory); }
/** * Remove all entries. */ @Override public synchronized void clear() { beforeWrite(); root.removeAllRecursive(); newRoot(Page.createEmpty(this, writeVersion)); }