@Override @SuppressWarnings("unchecked") public void visit(BranchNode branchNode, NodeStorageManager storage) { assert branchNode.mutable; Node<? extends Node<?>> bestChild = findWritableBestBranch(branchNode, item, storage); if (bestChild != null) { bestChild.accept(this, storage); return; } // Exceptional case - empty node. So do this last if (branchNode.getNumChildren() == 0) { // We are making a change so clone the node BranchNode updateBranch = storage.getWriteableBranch(branchNode.getRef()); LeafNode newLeaf = storage.createLeafNode(updateBranch.getRef()); updateBranch.add(new Branch((RefImpl) newLeaf.getRef())); newLeaf.accept(this, storage); return; } // FIXME: This happens if an enum splitter has been configured too small // we shouldn't need to pre-allocate the branches in that case throw new Error("InsertFailedException(item);"); }
/** * Begin a new search - use the helper Index.NewSearch() * * @param spec * @param nominee */ public OrderedSearch( SearchSpecImpl spec, IScoreConfiguration config, boolean nominee, NodeStorageManager storage) { super(); this.spec = spec; this.storage = storage; this.nominee = nominee; resultsQ = new ResultsQ(spec.getMaxNonMatches(), spec.getScoreThreshold(), spec.getTargetNumResults()); workQ = new WorkQ(this, resultsQ, config); workQ.add( new NextNode(new NodeScore(), getNextSeq(), storage.getRootNode())); // FIXME: NodeScore if (log.isInfoEnabled()) { log.info( "New Search: threshold = " + spec.getScoreThreshold() + ", targetNumResults = " + spec.getTargetNumResults() + ", searchType = " + spec.getScorerConfig()); } // log.info( "Index dump: "); // storage.getRootNode().dumpNode(System.out, 0, storage); }
private Node<? extends Node<?>> findWritableBestBranch( BranchNode branchNode, IAttributeContainer item, NodeStorageManager storage) { Node<? extends Node<?>> bestChild = null; int bestCount = Integer.MAX_VALUE; for (int i = 0; i < branchNode.numChildren; i++) { if (branchNode.children[i].consistent(item)) { Node<? extends Node<?>> child = branchNode.children[i].getWriteableChild(storage); // normal case is that we split, so first matching child is appropriate if (branchNode.children[i].getSplitId() != -1) { // i.e. hasSplit() return child; } if (child instanceof LeafNode) { LeafNode leaf = (LeafNode) child; // If children are LeafNode, and more than one qualifies, insert into the smallest one. // This is because we can split a node without splitting on an attribute, if the // attributes are // too close to split and no manager wants to split. int count = leaf.items.size(); if (count < bestCount) { bestCount = count; bestChild = child; } } else { int bestIndex = rand.nextInt(branchNode.numChildren); // rand between 0 to numChildren-1 return branchNode.children[bestIndex].getWriteableChild(storage); // was if (bestChild == null) bestChild = child; // prefer leaf node to branch node // if both qualify // break; } } } return (bestChild == null) ? null : storage.getWriteableNode(bestChild.getRef()); }