All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.druid.segment.incremental.IncrementalIndexStorageAdapter Maven / Gradle / Ivy
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.druid.segment.incremental;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import io.druid.java.util.common.granularity.Granularity;
import io.druid.java.util.common.guava.Sequence;
import io.druid.java.util.common.guava.Sequences;
import io.druid.query.BaseQuery;
import io.druid.query.QueryMetrics;
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.segment.Capabilities;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.Cursor;
import io.druid.segment.DimensionIndexer;
import io.druid.segment.Metadata;
import io.druid.segment.StorageAdapter;
import io.druid.segment.VirtualColumns;
import io.druid.segment.column.Column;
import io.druid.segment.column.ColumnCapabilities;
import io.druid.segment.data.Indexed;
import io.druid.segment.data.ListIndexed;
import io.druid.segment.filter.BooleanValueMatcher;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import javax.annotation.Nullable;
import java.util.Iterator;
/**
*/
public class IncrementalIndexStorageAdapter implements StorageAdapter
{
private final IncrementalIndex index;
public IncrementalIndexStorageAdapter(IncrementalIndex index)
{
this.index = index;
}
@Override
public String getSegmentIdentifier()
{
throw new UnsupportedOperationException();
}
@Override
public Interval getInterval()
{
return index.getInterval();
}
@Override
public Indexed getAvailableDimensions()
{
return new ListIndexed<>(index.getDimensionNames(), String.class);
}
@Override
public Iterable getAvailableMetrics()
{
return index.getMetricNames();
}
@Override
public int getDimensionCardinality(String dimension)
{
if (dimension.equals(Column.TIME_COLUMN_NAME)) {
return Integer.MAX_VALUE;
}
IncrementalIndex.DimensionDesc desc = index.getDimension(dimension);
if (desc == null) {
return 0;
}
DimensionIndexer indexer = index.getDimension(dimension).getIndexer();
return indexer.getCardinality();
}
@Override
public int getNumRows()
{
return index.size();
}
@Override
public DateTime getMinTime()
{
return index.getMinTime();
}
@Override
public DateTime getMaxTime()
{
return index.getMaxTime();
}
@Nullable
@Override
public Comparable getMinValue(String column)
{
IncrementalIndex.DimensionDesc desc = index.getDimension(column);
if (desc == null) {
return null;
}
DimensionIndexer indexer = desc.getIndexer();
return indexer.getMinValue();
}
@Nullable
@Override
public Comparable getMaxValue(String column)
{
IncrementalIndex.DimensionDesc desc = index.getDimension(column);
if (desc == null) {
return null;
}
DimensionIndexer indexer = desc.getIndexer();
return indexer.getMaxValue();
}
@Override
public Capabilities getCapabilities()
{
return Capabilities.builder().dimensionValuesSorted(false).build();
}
@Override
public ColumnCapabilities getColumnCapabilities(String column)
{
return index.getCapabilities(column);
}
@Override
public String getColumnTypeName(String column)
{
final String metricType = index.getMetricType(column);
return metricType != null ? metricType : getColumnCapabilities(column).getType().toString();
}
@Override
public DateTime getMaxIngestedEventTime()
{
return index.getMaxIngestedEventTime();
}
@Override
public Sequence makeCursors(
final Filter filter,
final Interval interval,
final VirtualColumns virtualColumns,
final Granularity gran,
final boolean descending,
@Nullable QueryMetrics queryMetrics
)
{
if (index.isEmpty()) {
return Sequences.empty();
}
final Interval dataInterval = new Interval(getMinTime(), gran.bucketEnd(getMaxTime()));
if (!interval.overlaps(dataInterval)) {
return Sequences.empty();
}
final Interval actualInterval = interval.overlap(dataInterval);
Iterable iterable = gran.getIterable(actualInterval);
if (descending) {
iterable = Lists.reverse(ImmutableList.copyOf(iterable));
}
return Sequences
.simple(iterable)
.map(i -> new IncrementalIndexCursor(virtualColumns, descending, filter, i, actualInterval, gran));
}
private ValueMatcher makeFilterMatcher(final Filter filter, final Cursor cursor)
{
return filter == null
? BooleanValueMatcher.of(true)
: filter.makeMatcher(cursor.getColumnSelectorFactory());
}
@Override
public Metadata getMetadata()
{
return index.getMetadata();
}
private class IncrementalIndexCursor implements Cursor
{
private TimeAndDimsHolder currEntry;
private final ColumnSelectorFactory columnSelectorFactory;
private final ValueMatcher filterMatcher;
private final int maxRowIndex;
private Iterator baseIter;
private Iterable cursorIterable;
private boolean emptyRange;
private final DateTime time;
private int numAdvanced;
private boolean done;
IncrementalIndexCursor(
VirtualColumns virtualColumns,
boolean descending,
Filter filter,
Interval interval,
Interval actualInterval,
Granularity gran
)
{
currEntry = new TimeAndDimsHolder();
columnSelectorFactory = new IncrementalIndexColumnSelectorFactory(index, virtualColumns, descending, currEntry);
filterMatcher = makeFilterMatcher(filter, this);
numAdvanced = -1;
maxRowIndex = index.getLastRowIndex();
final long timeStart = Math.max(interval.getStartMillis(), actualInterval.getStartMillis());
cursorIterable = index.getFacts().timeRangeIterable(
descending,
timeStart,
Math.min(actualInterval.getEndMillis(), gran.increment(interval.getStart()).getMillis())
);
emptyRange = !cursorIterable.iterator().hasNext();
time = gran.toDateTime(interval.getStartMillis());
reset();
}
@Override
public ColumnSelectorFactory getColumnSelectorFactory()
{
return columnSelectorFactory;
}
@Override
public DateTime getTime()
{
return time;
}
@Override
public void advance()
{
if (!baseIter.hasNext()) {
done = true;
return;
}
while (baseIter.hasNext()) {
BaseQuery.checkInterrupted();
IncrementalIndex.TimeAndDims entry = baseIter.next();
if (beyondMaxRowIndex(entry.getRowIndex())) {
continue;
}
currEntry.set(entry);
if (filterMatcher.matches()) {
return;
}
}
done = true;
}
@Override
public void advanceUninterruptibly()
{
if (!baseIter.hasNext()) {
done = true;
return;
}
while (baseIter.hasNext()) {
if (Thread.currentThread().isInterrupted()) {
return;
}
IncrementalIndex.TimeAndDims entry = baseIter.next();
if (beyondMaxRowIndex(entry.getRowIndex())) {
continue;
}
currEntry.set(entry);
if (filterMatcher.matches()) {
return;
}
}
done = true;
}
@Override
public void advanceTo(int offset)
{
int count = 0;
while (count < offset && !isDone()) {
advance();
count++;
}
}
@Override
public boolean isDone()
{
return done;
}
@Override
public boolean isDoneOrInterrupted()
{
return isDone() || Thread.currentThread().isInterrupted();
}
@Override
public void reset()
{
baseIter = cursorIterable.iterator();
if (numAdvanced == -1) {
numAdvanced = 0;
} else {
Iterators.advance(baseIter, numAdvanced);
}
BaseQuery.checkInterrupted();
boolean foundMatched = false;
while (baseIter.hasNext()) {
IncrementalIndex.TimeAndDims entry = baseIter.next();
if (beyondMaxRowIndex(entry.getRowIndex())) {
numAdvanced++;
continue;
}
currEntry.set(entry);
if (filterMatcher.matches()) {
foundMatched = true;
break;
}
numAdvanced++;
}
done = !foundMatched && (emptyRange || !baseIter.hasNext());
}
private boolean beyondMaxRowIndex(int rowIndex)
{
// ignore rows whose rowIndex is beyond the maxRowIndex
// rows are order by timestamp, not rowIndex,
// so we still need to go through all rows to skip rows added after cursor created
return rowIndex > maxRowIndex;
}
}
}