/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.github.geophile.erdo.map.forestmap;
import com.github.geophile.erdo.AbstractKey;
import com.github.geophile.erdo.forest.ForestSnapshot;
import com.github.geophile.erdo.map.MapCursor;
import java.io.IOException;
import java.util.logging.Logger;
/*
* A Forest has several trees. The keys of a tree are kept in memory except for a few of the
* biggest trees. These in-memory keys are used to speed up ForestMap scans.
*
* A ForestMap cursor can be done in two ways:
* 1) Put all of the forest's trees into a MergeCursor.
* 2) Merge the keys of the biggest trees (whose keys are not in memory) with the in-memory keys
* from the smaller trees. This merge yields the newest version of each key. For each key provided
* by the merge, find the associated record.
*
* For a complete cursor, #2 might be a little faster, possibly avoiding an occasional big-tree page
* containing nothing but obsolete records.
*
* For a narrow cursor, #2 should be a lot better. For example, suppose we have a forest with 100
* trees and a cursor that yields 10 records. With #1 we have to probe all 100 trees, just to
* start each tree cursor. With #2 we probe at most 10 trees, because we know exactly which
* trees have relevant records.
*
* A probably important special case is a cursor with start = end. There are three possibilities
* (k = start = end):
* a) k does not exist in any tree in the forest. The in-memory keys do not contain k so we search
* all big tree.
* b) k is only in one or more big trees. Again, we search just the big trees.
* c) k is in one or more big trees and in the in-memory keys, (i.e., k has been updated recently).
* In this case, we search one small tree and we're done.
*
* So we want to implement #2, to optimize start = end scans. This case is handled by
* ForestMapMatchCursor. All other scans are handled by ForestMapRangeCursor, which implements #1.
*/
public abstract class ForestMapCursor extends MapCursor
{
// ForestMapCursor interface
public static ForestMapCursor newCursor(ForestSnapshot forestSnapshot,
AbstractKey startKey,
boolean singleKey)
throws IOException, InterruptedException
{
assert !(startKey == null && singleKey);
return
singleKey
? new ForestMapMatchCursor(forestSnapshot, startKey)
: new ForestMapRangeCursor(forestSnapshot, startKey);
}
// For use by subclasses
protected ForestMapCursor(ForestSnapshot forestSnapshot, AbstractKey startKey, boolean singleKey)
throws IOException, InterruptedException
{
super(startKey, singleKey);
this.forestSnapshot = forestSnapshot;
}
// Class state
protected static final Logger LOG = Logger.getLogger(ForestMapCursor.class.getName());
// Object state
protected final ForestSnapshot forestSnapshot;
}