return _rootPageNumber;
}
- protected void addedUniqueEntry() {
- ++_uniqueEntryCount;
- }
-
protected void setReadOnly() {
_readOnly = true;
}
protected int getMaxPageEntrySize() {
return _maxPageEntrySize;
}
+
+ /**
+ * Returns the number of index entries in the index. Only called by unit
+ * tests.
+ * <p>
+ * Forces index initialization.
+ */
+ protected int getEntryCount()
+ throws IOException
+ {
+ initialize();
+ EntryCursor cursor = cursor();
+ Entry endEntry = cursor.getLastEntry();
+ int count = 0;
+ while(!endEntry.equals(cursor.getNextEntry())) {
+ ++count;
+ }
+ return count;
+ }
/**
* Forces initialization of this index (actual parsing of index pages).
}
}
+ /**
+ * Adds an entry to the correct index dataPage, maintaining the order.
+ */
+ private boolean addEntry(Entry newEntry, boolean isNullEntry, Object[] row)
+ throws IOException
+ {
+ DataPage dataPage = findDataPage(newEntry);
+ int idx = dataPage.findEntry(newEntry);
+ if(idx < 0) {
+ // this is a new entry
+ idx = missingIndexToInsertionPoint(idx);
+
+ Position newPos = new Position(dataPage, idx, newEntry, true);
+ Position nextPos = getNextPosition(newPos);
+ Position prevPos = getPreviousPosition(newPos);
+
+ // determine if the addition of this entry would break the uniqueness
+ // constraint. See isUnique() for some notes about uniqueness as
+ // defined by Access.
+ boolean isDupeEntry =
+ (((nextPos != null) &&
+ newEntry.equalsEntryBytes(nextPos.getEntry())) ||
+ ((prevPos != null) &&
+ newEntry.equalsEntryBytes(prevPos.getEntry())));
+ if(isUnique() && !isNullEntry && isDupeEntry)
+ {
+ throw new IOException(
+ "New row " + Arrays.asList(row) +
+ " violates uniqueness constraint for index " + this);
+ }
+
+ if(!isDupeEntry) {
+ ++_uniqueEntryCount;
+ }
+
+ dataPage.addEntry(idx, newEntry);
+ return true;
+ }
+ return false;
+ }
+
/**
* Removes a row from this index
* <p>
}
}
+ /**
+ * Removes an entry from the relevant index dataPage, maintaining the order.
+ * Will search by RowId if entry is not found (in case a partial entry was
+ * provided).
+ */
+ private boolean removeEntry(Entry oldEntry)
+ throws IOException
+ {
+ DataPage dataPage = findDataPage(oldEntry);
+ int idx = dataPage.findEntry(oldEntry);
+ boolean doRemove = false;
+ if(idx < 0) {
+ // the caller may have only read some of the row data, if this is the
+ // case, just search for the page/row numbers
+ // FIXME, we could force caller to get relevant values?
+ EntryCursor cursor = cursor();
+ Position tmpPos = null;
+ Position endPos = cursor._lastPos;
+ while(!endPos.equals(
+ tmpPos = cursor.getAnotherPosition(Cursor.MOVE_FORWARD))) {
+ if(tmpPos.getEntry().getRowId().equals(oldEntry.getRowId())) {
+ dataPage = tmpPos.getDataPage();
+ idx = tmpPos.getIndex();
+ doRemove = true;
+ break;
+ }
+ }
+ } else {
+ doRemove = true;
+ }
+
+ if(doRemove) {
+ // found it!
+ dataPage.removeEntry(idx);
+ }
+
+ return doRemove;
+ }
+
/**
* Gets a new cursor for this index.
* <p>
return new Position(dataPage, idx, entry, between);
}
- private Position getNextPosition(Position curPos, Position lastPos)
+ private Position getNextPosition(Position curPos)
throws IOException
{
// get the next index (between-ness is handled internally)
}
if(nextDataPage != null) {
nextPos = new Position(nextDataPage, nextIdx);
- } else {
- nextPos = lastPos;
}
}
- if(nextPos.compareTo(lastPos) >= 0) {
- nextPos = lastPos;
- }
return nextPos;
}
-
- private Position getPreviousPosition(Position curPos, Position firstPos)
+
+ /**
+ * Returns the Position before the given one, or {@code null} if none.
+ */
+ private Position getPreviousPosition(Position curPos)
throws IOException
{
// get the previous index (between-ness is handled internally)
if(prevDataPage != null) {
prevPos = new Position(prevDataPage,
(prevDataPage.getEntries().size() - 1));
- } else {
- prevPos = firstPos;
}
}
- if(prevPos.compareTo(firstPos) <= 0) {
- prevPos = firstPos;
- }
return prevPos;
}
return bout.toByteArray();
}
- /**
- * Returns the number of index entries in the index. Only called by unit
- * tests.
- * <p>
- * Forces index initialization.
- */
- protected abstract int getEntryCount() throws IOException;
-
/**
* Writes the current index state to the database. Index has already been
* initialized.
*/
protected abstract void readIndexEntries()
throws IOException;
-
- /**
- * Adds an entry to the _entries list, maintaining the order.
- */
- protected abstract boolean addEntry(Entry newEntry, boolean isNullEntry,
- Object[] row)
- throws IOException;
-
- /**
- * Removes an entry from the _entries list, maintaining the order. Will
- * search by RowId if entry is not found in case a partial entry was
- * provided.
- */
- protected abstract boolean removeEntry(Entry oldEntry)
- throws IOException;
/**
* Finds the data page for the given entry.
* {@code #getLastEntry} otherwise
*/
public Entry getNextEntry() throws IOException {
- return getAnotherEntry(Cursor.MOVE_FORWARD);
+ return getAnotherPosition(Cursor.MOVE_FORWARD).getEntry();
}
/**
* {@code #getFirstEntry} otherwise
*/
public Entry getPreviousEntry() throws IOException {
- return getAnotherEntry(Cursor.MOVE_REVERSE);
+ return getAnotherPosition(Cursor.MOVE_REVERSE).getEntry();
}
/**
/**
* Gets another entry in the given direction, returning the new entry.
*/
- private Entry getAnotherEntry(boolean moveForward)
+ private Position getAnotherPosition(boolean moveForward)
throws IOException
{
DirHandler handler = getDirHandler(moveForward);
// drop through and retry moving to another entry
} else {
// at end, no more
- return _curPos.getEntry();
+ return _curPos;
}
}
_prevPos = _curPos;
_curPos = handler.getAnotherPosition(_curPos);
- return _curPos.getEntry();
+ return _curPos;
}
/**
public Position getAnotherPosition(Position curPos)
throws IOException
{
- return getNextPosition(curPos, _lastPos);
+ Position newPos = getNextPosition(curPos);
+ if((newPos == null) || (newPos.compareTo(_lastPos) >= 0)) {
+ newPos = _lastPos;
+ }
+ return newPos;
}
@Override
public Position getBeginningPosition() {
public Position getAnotherPosition(Position curPos)
throws IOException
{
- return getPreviousPosition(curPos, _firstPos);
+ Position newPos = getPreviousPosition(curPos);
+ if((newPos == null) || (newPos.compareTo(_firstPos) <= 0)) {
+ newPos = _firstPos;
+ }
+ return newPos;
}
@Override
public Position getBeginningPosition() {
public abstract List<Entry> getEntries();
public abstract void setEntries(List<Entry> entries);
+
+ public abstract void addEntry(int idx, Entry entry);
+ public abstract void removeEntry(int idx);
public final int getCompressedEntrySize() {
// when written to the index page, the entryPrefix bytes will only be
super(table, uniqueEntryCount, uniqueEntryCountOffset);
}
- private List<Entry> getEntries() {
- return _dataPage.getEntries();
- }
-
- @Override
- protected int getEntryCount()
- throws IOException
- {
- initialize();
- return getEntries().size();
- }
-
@Override
protected void updateImpl() throws IOException {
writeDataPage(_dataPage);
}
}
- /**
- * Finds the index of given entry in the entries list.
- * @return the index if found, (-<insertion_point> - 1) if not found
- */
- private int findEntry(Entry entry) {
- return Collections.binarySearch(getEntries(), entry);
- }
-
- @Override
- protected boolean addEntry(Entry newEntry, boolean isNullEntry, Object[] row)
- throws IOException
- {
- int idx = findEntry(newEntry);
- if(idx < 0) {
- // this is a new entry
- idx = missingIndexToInsertionPoint(idx);
-
- // determine if the addition of this entry would break the uniqueness
- // constraint. See isUnique() for some notes about uniqueness as
- // defined by Access.
- boolean isDupeEntry =
- (((idx > 0) &&
- newEntry.equalsEntryBytes(getEntries().get(idx - 1))) ||
- ((idx < getEntries().size()) &&
- newEntry.equalsEntryBytes(getEntries().get(idx))));
- if(isUnique() && !isNullEntry && isDupeEntry)
- {
- throw new IOException(
- "New row " + Arrays.asList(row) +
- " violates uniqueness constraint for index " + this);
- }
-
- if(!isDupeEntry) {
- addedUniqueEntry();
- }
-
- getEntries().add(idx, newEntry);
- return true;
- }
- return false;
- }
-
- @Override
- protected boolean removeEntry(Entry oldEntry)
- {
- int idx = findEntry(oldEntry);
- boolean removed = false;
- if(idx < 0) {
- // the caller may have only read some of the row data, if this is the
- // case, just search for the page/row numbers
- for(Iterator<Entry> iter = getEntries().iterator(); iter.hasNext(); ) {
- Entry entry = iter.next();
- if(entry.getRowId().equals(oldEntry.getRowId())) {
- iter.remove();
- removed = true;
- break;
- }
- }
- } else {
- // found it!
- getEntries().remove(idx);
- removed = true;
- }
-
- return removed;
- }
-
@Override
protected DataPage findDataPage(Entry entry)
throws IOException
_entries = entries;
}
+
+ @Override
+ public void addEntry(int idx, Entry entry) {
+ _entries.add(idx, entry);
+ }
+
+ public void removeEntry(int idx) {
+ _entries.remove(idx);
+ }
+
}
}