use of com.hazelcast.query.impl.InternalIndex in project hazelcast by hazelcast.
the class IndexRangeFilterIteratorTest method testIterator_simple_to.
@Test
public void testIterator_simple_to() {
HazelcastInstance instance = factory.newHazelcastInstance(getConfig());
IMap<Integer, Value> map = instance.getMap(MAP_NAME);
map.addIndex(new IndexConfig().setName(INDEX_NAME).setType(SORTED).addAttribute("value1"));
InternalIndex index = getIndex(instance);
ExpressionEvalContext evalContext = createExpressionEvalContext();
// Check missing value.
map.put(0, new Value(10));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), false).getEntries(index, descendingDirection, evalContext));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), true).getEntries(index, descendingDirection, evalContext));
// Check single value.
map.put(1, new Value(2));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), false).getEntries(index, descendingDirection, evalContext));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), true).getEntries(index, descendingDirection, evalContext), 1);
// Check multiple values.
map.put(2, new Value(2));
map.put(3, new Value(1));
map.put(4, new Value(1));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), false).getEntries(index, descendingDirection, evalContext), 3, 4);
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(2), true).getEntries(index, descendingDirection, evalContext), 1, 2, 3, 4);
// Check null value.
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(null, false), false).getEntries(index, descendingDirection, evalContext));
checkIterator(SORTED, descendingDirection, new IndexRangeFilter(null, false, intValue(null, false), true).getEntries(index, descendingDirection, evalContext));
}
use of com.hazelcast.query.impl.InternalIndex in project hazelcast by hazelcast.
the class MapReplicationStateHolder method applyState.
@SuppressWarnings({ "checkstyle:npathcomplexity", "checkstyle:methodlength", "checkstyle:cyclomaticcomplexity", "checkstyle:nestedifdepth" })
void applyState() {
ThreadUtil.assertRunningOnPartitionThread();
applyIndexesState();
if (!isNullOrEmpty(data)) {
for (Map.Entry<String, List> dataEntry : data.entrySet()) {
String mapName = dataEntry.getKey();
List keyRecordExpiry = dataEntry.getValue();
RecordStore recordStore = operation.getRecordStore(mapName);
recordStore.beforeOperation();
try {
initializeRecordStore(mapName, recordStore);
recordStore.setPreMigrationLoadedStatus(loaded.get(mapName));
MapContainer mapContainer = recordStore.getMapContainer();
PartitionContainer partitionContainer = recordStore.getMapContainer().getMapServiceContext().getPartitionContainer(operation.getPartitionId());
for (Map.Entry<String, IndexConfig> indexDefinition : mapContainer.getIndexDefinitions().entrySet()) {
Indexes indexes = mapContainer.getIndexes(partitionContainer.getPartitionId());
indexes.addOrGetIndex(indexDefinition.getValue());
}
final Indexes indexes = mapContainer.getIndexes(partitionContainer.getPartitionId());
final boolean populateIndexes = indexesMustBePopulated(indexes, operation);
InternalIndex[] indexesSnapshot = null;
if (populateIndexes) {
// defensively clear possible stale leftovers in non-global indexes from
// the previous failed promotion attempt
indexesSnapshot = indexes.getIndexes();
Indexes.beginPartitionUpdate(indexesSnapshot);
indexes.clearAll();
}
long nowInMillis = Clock.currentTimeMillis();
forEachReplicatedRecord(keyRecordExpiry, mapContainer, recordStore, populateIndexes, nowInMillis);
if (populateIndexes) {
Indexes.markPartitionAsIndexed(partitionContainer.getPartitionId(), indexesSnapshot);
}
} finally {
recordStore.afterOperation();
}
}
}
for (Map.Entry<String, LocalRecordStoreStats> statsEntry : recordStoreStatsPerMapName.entrySet()) {
String mapName = statsEntry.getKey();
LocalRecordStoreStats stats = statsEntry.getValue();
RecordStore recordStore = operation.getRecordStore(mapName);
recordStore.setStats(stats);
}
}
use of com.hazelcast.query.impl.InternalIndex in project hazelcast by hazelcast.
the class CompositeIndexVisitor method visit.
@SuppressWarnings({ "checkstyle:cyclomaticcomplexity", "checkstyle:methodlength", "checkstyle:npathcomplexity" })
@Override
public Predicate visit(AndPredicate andPredicate, Indexes indexes) {
int originalSize = andPredicate.predicates.length;
if (originalSize < 2) {
// can't optimize further
return andPredicate;
}
InternalIndex[] compositeIndexes = indexes.getCompositeIndexes();
if (compositeIndexes.length == 0) {
// no composite indexes to optimize against
return andPredicate;
}
// 1. Split predicates into 3 groups: (a) prefixes, that are equal
// predicates, like a == 1; (b) comparisons, that are order comparisons
// predicates, like a > 1; (c) output, this group contains unoptimizable
// predicates, like a != 1; later, the group also receives optimized
// predicates ready for output.
Map<String, EqualPredicate> prefixes = null;
Map<String, RangePredicate> comparisons = null;
Output output = null;
for (Predicate predicate : andPredicate.predicates) {
if (predicate instanceof EqualPredicate) {
EqualPredicate equalPredicate = (EqualPredicate) predicate;
prefixes = obtainHashMap(prefixes, originalSize);
EqualPredicate replaced = prefixes.put(equalPredicate.attributeName, equalPredicate);
if (replaced != null) {
// If we have multiple predicates for the same attribute,
// that means RangeVisitor is failed to optimize them. In
// turn, that means the range visitor was unable to find
// a TypeConverter for the attribute and that means the map
// and/or index were empty at the moment.
//
// So we record duplicates in the output and produce an
// underoptimized result in the end.
output = obtainOutput(output, originalSize);
output.add(replaced);
}
continue;
}
if (predicate instanceof RangePredicate) {
RangePredicate rangePredicate = (RangePredicate) predicate;
comparisons = obtainHashMap(comparisons, originalSize);
RangePredicate replaced = comparisons.put(rangePredicate.getAttribute(), rangePredicate);
if (replaced != null) {
output = obtainOutput(output, originalSize);
output.add(replaced);
}
continue;
}
output = obtainOutput(output, originalSize);
output.add(predicate);
}
if (prefixes == null || comparisons == null && prefixes.size() == 1) {
// no comparisons that can be matched to form a prefix of length 2.
return andPredicate;
}
assert !prefixes.isEmpty();
while (!prefixes.isEmpty()) {
int bestPrefix = 0;
InternalIndex bestIndex = null;
RangePredicate bestComparison = null;
for (InternalIndex index : compositeIndexes) {
String[] components = index.getComponents();
if (components.length < bestPrefix || !index.isOrdered() && prefixes.size() < components.length) {
// fewer components to match than the index has.
continue;
}
int prefix = 0;
while (prefix < components.length && prefixes.containsKey(components[prefix])) {
++prefix;
}
if (prefix == 0) {
// no prefix found at all
continue;
}
if (index.isOrdered()) {
RangePredicate comparison = prefix < components.length && comparisons != null ? comparisons.get(components[prefix]) : null;
if (comparison != null) {
++prefix;
}
if (prefix > bestPrefix) {
bestPrefix = prefix;
bestIndex = index;
bestComparison = comparison;
} else if (prefix == bestPrefix) {
// the matched prefix is at least of length 1
assert bestIndex != null;
if (bestIndex.isOrdered() && bestIndex.getComponents().length > components.length) {
// prefer shorter indexes over longer ones
bestIndex = index;
bestComparison = comparison;
}
}
} else if (prefix == components.length && prefix >= bestPrefix) {
// The unordered index components are fully matched and the
// prefix is longer or equal to the best found prefix. The
// later is needed to give a preference for unordered matches
// over ordered ones.
bestPrefix = prefix;
bestIndex = index;
bestComparison = null;
}
}
if (bestIndex == null || bestPrefix == 1) {
// should be handled by AttributeIndexRegistry.
break;
}
// exclude the comparison from the prefix, just to make the math simpler later
int equalPrefixLength = bestComparison == null ? bestPrefix : bestPrefix - 1;
if (output == null) {
// if we have no output yet, try to perform a cheaper fast exit
Predicate generated = tryGenerateFast(prefixes, comparisons, equalPrefixLength, bestComparison, bestIndex);
if (generated != null) {
return generated;
}
}
output = obtainOutput(output, originalSize);
addToOutput(prefixes, comparisons, output, equalPrefixLength, bestComparison, bestIndex);
}
return output == null ? andPredicate : output.generate(prefixes, comparisons, andPredicate);
}
use of com.hazelcast.query.impl.InternalIndex in project hazelcast by hazelcast.
the class AddIndexOperation method runInternal.
@Override
public void runInternal() {
int partitionId = getPartitionId();
Indexes indexes = mapContainer.getIndexes(partitionId);
InternalIndex index = indexes.addOrGetIndex(config);
if (index.hasPartitionIndexed(partitionId)) {
return;
}
SerializationService serializationService = getNodeEngine().getSerializationService();
index.beginPartitionUpdate();
CacheDeserializedValues cacheDeserializedValues = mapContainer.getMapConfig().getCacheDeserializedValues();
CachedQueryEntry<?, ?> cachedEntry = cacheDeserializedValues == NEVER ? new CachedQueryEntry<>(serializationService, mapContainer.getExtractors()) : null;
recordStore.forEach((dataKey, record) -> {
Object value = Records.getValueOrCachedValue(record, serializationService);
QueryableEntry<?, ?> queryEntry = mapContainer.newQueryEntry(dataKey, value);
queryEntry.setRecord(record);
CachedQueryEntry<?, ?> newEntry = cachedEntry == null ? (CachedQueryEntry<?, ?>) queryEntry : cachedEntry.init(dataKey, value);
index.putEntry(newEntry, null, queryEntry, Index.OperationSource.USER);
}, false);
index.markPartitionAsIndexed(partitionId);
}
use of com.hazelcast.query.impl.InternalIndex in project hazelcast by hazelcast.
the class CompositeIndexVisitorTest method before.
@Before
public void before() {
indexes = mock(Indexes.class);
o123 = mock(InternalIndex.class);
when(o123.isOrdered()).thenReturn(true);
when(o123.getComponents()).thenReturn(components("a1", "a2", "a3"));
u321 = mock(InternalIndex.class);
when(u321.isOrdered()).thenReturn(false);
when(u321.getComponents()).thenReturn(components("a3", "a2", "a1"));
o567 = mock(InternalIndex.class);
when(o567.isOrdered()).thenReturn(true);
when(o567.getComponents()).thenReturn(components("a5", "a6", "a7"));
// needed to test the preference of shorter indexes over longer ones
InternalIndex o1234 = mock(InternalIndex.class);
when(o1234.isOrdered()).thenReturn(true);
when(o1234.getComponents()).thenReturn(components("a1", "a2", "a3", "a4"));
when(indexes.getCompositeIndexes()).thenReturn(new InternalIndex[] { o1234, o123, u321, o567 });
visitor = new CompositeIndexVisitor();
}
Aggregations