/*
* Copyright 2004-2019 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.index;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.store.Data;
import org.h2.store.Page;
A page that contains data rows.
/**
* A page that contains data rows.
*/
abstract class PageData extends Page {
The position of the parent page id.
/**
* The position of the parent page id.
*/
static final int START_PARENT = 3;
This is a root page.
/**
* This is a root page.
*/
static final int ROOT = 0;
Indicator that the row count is not known.
/**
* Indicator that the row count is not known.
*/
static final int UNKNOWN_ROWCOUNT = -1;
The index.
/**
* The index.
*/
protected final PageDataIndex index;
The page number of the parent.
/**
* The page number of the parent.
*/
protected int parentPageId;
The data page.
/**
* The data page.
*/
protected final Data data;
The number of entries.
/**
* The number of entries.
*/
protected int entryCount;
The row keys.
/**
* The row keys.
*/
protected long[] keys;
Whether the data page is up-to-date.
/**
* Whether the data page is up-to-date.
*/
protected boolean written;
The estimated heap memory used by this object, in number of double words
(4 bytes each).
/**
* The estimated heap memory used by this object, in number of double words
* (4 bytes each).
*/
private final int memoryEstimated;
PageData(PageDataIndex index, int pageId, Data data) {
this.index = index;
this.data = data;
setPos(pageId);
memoryEstimated = index.getMemoryPerPage();
}
Get the real row count. If required, this will read all child pages.
Returns: the row count
/**
* Get the real row count. If required, this will read all child pages.
*
* @return the row count
*/
abstract int getRowCount();
Set the stored row count. This will write the page.
Params: - rowCount – the stored row count
/**
* Set the stored row count. This will write the page.
*
* @param rowCount the stored row count
*/
abstract void setRowCountStored(int rowCount);
Get the used disk space for this index.
Returns: the estimated number of bytes
/**
* Get the used disk space for this index.
*
* @return the estimated number of bytes
*/
abstract long getDiskSpaceUsed();
Find an entry by key.
Params: - key – the key (may not exist)
Returns: the matching or next index
/**
* Find an entry by key.
*
* @param key the key (may not exist)
* @return the matching or next index
*/
int find(long key) {
int l = 0, r = entryCount;
while (l < r) {
int i = (l + r) >>> 1;
long k = keys[i];
if (k == key) {
return i;
} else if (k > key) {
r = i;
} else {
l = i + 1;
}
}
return l;
}
Add a row if possible. If it is possible this method returns -1,
otherwise the split point. It is always possible to add one row.
Params: - row – the now to add
Returns: the split point of this page, or -1 if no split is required
/**
* Add a row if possible. If it is possible this method returns -1,
* otherwise the split point. It is always possible to add one row.
*
* @param row the now to add
* @return the split point of this page, or -1 if no split is required
*/
abstract int addRowTry(Row row);
Get a cursor.
Params: - session – the session
- minKey – the smallest key
- maxKey – the largest key
Returns: the cursor
/**
* Get a cursor.
*
* @param session the session
* @param minKey the smallest key
* @param maxKey the largest key
* @return the cursor
*/
abstract Cursor find(Session session, long minKey, long maxKey);
Get the key at this position.
Params: - at – the index
Returns: the key
/**
* Get the key at this position.
*
* @param at the index
* @return the key
*/
long getKey(int at) {
return keys[at];
}
Split the index page at the given point.
Params: - splitPoint – the index where to split
Returns: the new page that contains about half the entries
/**
* Split the index page at the given point.
*
* @param splitPoint the index where to split
* @return the new page that contains about half the entries
*/
abstract PageData split(int splitPoint);
Change the page id.
Params: - id – the new page id
/**
* Change the page id.
*
* @param id the new page id
*/
void setPageId(int id) {
int old = getPos();
index.getPageStore().removeFromCache(getPos());
setPos(id);
index.getPageStore().logUndo(this, null);
remapChildren(old);
}
Get the last key of a page.
Returns: the last key
/**
* Get the last key of a page.
*
* @return the last key
*/
abstract long getLastKey();
Get the first child leaf page of a page.
Returns: the page
/**
* Get the first child leaf page of a page.
*
* @return the page
*/
abstract PageDataLeaf getFirstLeaf();
Change the parent page id.
Params: - id – the new parent page id
/**
* Change the parent page id.
*
* @param id the new parent page id
*/
void setParentPageId(int id) {
index.getPageStore().logUndo(this, data);
parentPageId = id;
if (written) {
changeCount = index.getPageStore().getChangeCount();
data.setInt(START_PARENT, parentPageId);
}
}
Update the parent id of all children.
Params: - old – the previous position
/**
* Update the parent id of all children.
*
* @param old the previous position
*/
abstract void remapChildren(int old);
Remove a row.
Params: - key – the key of the row to remove
Returns: true if this page is now empty
/**
* Remove a row.
*
* @param key the key of the row to remove
* @return true if this page is now empty
*/
abstract boolean remove(long key);
Free this page and all child pages.
/**
* Free this page and all child pages.
*/
abstract void freeRecursive();
Get the row for the given key.
Params: - key – the key
Returns: the row
/**
* Get the row for the given key.
*
* @param key the key
* @return the row
*/
abstract Row getRowWithKey(long key);
Get the estimated heap memory size.
Returns: number of double words (4 bytes each)
/**
* Get the estimated heap memory size.
*
* @return number of double words (4 bytes each)
*/
@Override
public int getMemory() {
// need to always return the same value for the same object (otherwise
// the cache size would change after adding and then removing the same
// page from the cache) but index.getMemoryPerPage() can adopt according
// to how much memory a row needs on average
return memoryEstimated;
}
int getParentPageId() {
return parentPageId;
}
@Override
public boolean canRemove() {
return changeCount < index.getPageStore().getChangeCount();
}
}