private static boolean isHashable(IndexableConstraint indexableConstraint) { return indexableConstraint.isIndexable(NodeTypeEnums.AlphaNode) && indexableConstraint.getField() != null && indexableConstraint.getFieldExtractor().getValueType() != ValueType.OBJECT_TYPE && // our current implementation does not support hashing of deeply nested properties indexableConstraint.getFieldExtractor().getIndex() >= 0; }
static InternalReadAccessor getHashableAccessor(AlphaNode alphaNode) { AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); if (fieldConstraint instanceof IndexableConstraint) { IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; if (isHashable(indexableConstraint)) { return indexableConstraint.getFieldExtractor(); } } return null; }
public ObjectSinkPropagator removeObjectSink(final ObjectSink sink) { this.sinks = null; // dirty it, so it'll rebuild on next get if (sink.getType() == NodeTypeEnums.AlphaNode) { final AlphaNode alphaNode = (AlphaNode) sink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); if (fieldConstraint instanceof IndexableConstraint) { final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; final FieldValue value = indexableConstraint.getField(); if (isHashable(indexableConstraint)) { final InternalReadAccessor fieldAccessor = indexableConstraint.getFieldExtractor(); final int index = fieldAccessor.getIndex(); final FieldIndex fieldIndex = unregisterFieldIndex(index); if (fieldIndex.isHashed()) { HashKey hashKey = new HashKey(index, value, fieldAccessor); this.hashedSinkMap.remove(hashKey); if (fieldIndex.getCount() <= this.alphaNodeHashingThreshold - 1) { // we have less than three so unhash unHashSinks(fieldIndex); } } else { this.hashableSinks.remove(alphaNode); } if (this.hashableSinks != null && this.hashableSinks.isEmpty()) { this.hashableSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; } } } this.otherSinks.remove((ObjectSinkNode) sink); if (this.otherSinks.isEmpty()) { this.otherSinks = null; } return size() == 1 ? new SingleObjectSinkAdapter(getSinks()[0]) : this; }
void unHashSinks(final FieldIndex fieldIndex) { final int index = fieldIndex.getIndex(); // this is the list of sinks that need to be removed from the hashedSinkMap final List<HashKey> unhashedSinks = new ArrayList<HashKey>(); final Iterator iter = this.hashedSinkMap.newIterator(); ObjectHashMap.ObjectEntry entry = (ObjectHashMap.ObjectEntry) iter.next(); while (entry != null) { final AlphaNode alphaNode = (AlphaNode) entry.getValue(); final IndexableConstraint indexableConstraint = (IndexableConstraint) alphaNode.getConstraint(); // only alpha nodes that have an Operator.EQUAL are in sinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); if (this.hashableSinks == null) { this.hashableSinks = new ObjectSinkNodeList(); } this.hashableSinks.add(alphaNode); unhashedSinks.add(new HashKey(index, value, fieldIndex.getFieldExtractor())); } entry = (ObjectHashMap.ObjectEntry) iter.next(); } for (HashKey hashKey : unhashedSinks) { this.hashedSinkMap.remove(hashKey); } if (this.hashedSinkMap.isEmpty()) { this.hashedSinkMap = null; } fieldIndex.setHashed(false); }
void hashSinks(final FieldIndex fieldIndex) { if (this.hashedSinkMap == null) { this.hashedSinkMap = new ObjectHashMap(); } final int index = fieldIndex.getIndex(); final InternalReadAccessor fieldReader = fieldIndex.getFieldExtractor(); ObjectSinkNode currentSink = this.hashableSinks.getFirst(); while (currentSink != null) { final AlphaNode alphaNode = (AlphaNode) currentSink; final AlphaNodeFieldConstraint fieldConstraint = alphaNode.getConstraint(); final IndexableConstraint indexableConstraint = (IndexableConstraint) fieldConstraint; // position to the next sink now because alphaNode may be removed if the index is equal. If we // were to do this // afterwards, currentSink.nextNode would be null currentSink = currentSink.getNextObjectSinkNode(); // only alpha nodes that have an Operator.EQUAL are in hashableSinks, so only check if it is // the right field index if (index == indexableConstraint.getFieldExtractor().getIndex()) { final FieldValue value = indexableConstraint.getField(); this.hashedSinkMap.put(new HashKey(index, value, fieldReader), alphaNode); // remove the alpha from the possible candidates of hashable sinks since it is now hashed hashableSinks.remove(alphaNode); } } if (this.hashableSinks.isEmpty()) { this.hashableSinks = null; } fieldIndex.setHashed(true); }