@Override public void hashRow(DimensionSelector dimSelector, Hasher hasher) { final IndexedInts row = dimSelector.getRow(); final int size = row.size(); // nothing to add to hasher if size == 0, only handle size == 1 and size != 0 cases. if (size == 1) { final String value = dimSelector.lookupName(row.get(0)); hasher.putUnencodedChars(nullToSpecial(value)); } else if (size != 0) { final String[] values = new String[size]; for (int i = 0; i < size; ++i) { final String value = dimSelector.lookupName(row.get(i)); values[i] = nullToSpecial(value); } // Values need to be sorted to ensure consistent multi-value ordering across different // segments Arrays.sort(values); for (int i = 0; i < size; ++i) { if (i != 0) { hasher.putChar(CARDINALITY_AGG_SEPARATOR); } hasher.putUnencodedChars(values[i]); } } }
@Test public void testResetSanity() throws IOException { IncrementalIndex index = indexCreator.createIndex(); DateTime t = DateTime.now(); Interval interval = new Interval(t.minusMinutes(1), t.plusMinutes(1)); index.add( new MapBasedInputRow( t.minus(1).getMillis(), Lists.newArrayList("billy"), ImmutableMap.<String, Object>of("billy", "hi"))); index.add( new MapBasedInputRow( t.minus(1).getMillis(), Lists.newArrayList("sally"), ImmutableMap.<String, Object>of("sally", "bo"))); IncrementalIndexStorageAdapter adapter = new IncrementalIndexStorageAdapter(index); for (boolean descending : Arrays.asList(false, true)) { Sequence<Cursor> cursorSequence = adapter.makeCursors( new SelectorFilter("sally", "bo"), interval, QueryGranularity.NONE, descending); Cursor cursor = Sequences.toList(Sequences.limit(cursorSequence, 1), Lists.<Cursor>newArrayList()).get(0); DimensionSelector dimSelector; dimSelector = cursor.makeDimensionSelector(new DefaultDimensionSpec("sally", "sally")); Assert.assertEquals("bo", dimSelector.lookupName(dimSelector.getRow().get(0))); index.add( new MapBasedInputRow( t.minus(1).getMillis(), Lists.newArrayList("sally"), ImmutableMap.<String, Object>of("sally", "ah"))); // Cursor reset should not be affected by out of order values cursor.reset(); dimSelector = cursor.makeDimensionSelector(new DefaultDimensionSpec("sally", "sally")); Assert.assertEquals("bo", dimSelector.lookupName(dimSelector.getRow().get(0))); } }
@Override public void hashValues(DimensionSelector dimSelector, HyperLogLogCollector collector) { for (IntIterator rowIt = dimSelector.getRow().iterator(); rowIt.hasNext(); ) { int index = rowIt.nextInt(); final String value = dimSelector.lookupName(index); collector.add( CardinalityAggregator.hashFn.hashUnencodedChars(nullToSpecial(value)).asBytes()); } }
@Override public DimensionSelector decorate(final DimensionSelector selector) { if (selector == null) { return selector; } int count = 0; final Map<Integer, Integer> forwardMapping = new HashMap<>(); for (int i = 0; i < selector.getValueCardinality(); i++) { if (compiledRegex.matcher(Strings.nullToEmpty(selector.lookupName(i))).matches()) { forwardMapping.put(i, count++); } } final int[] reverseMapping = new int[forwardMapping.size()]; for (Map.Entry<Integer, Integer> e : forwardMapping.entrySet()) { reverseMapping[e.getValue().intValue()] = e.getKey().intValue(); } return BaseFilteredDimensionSpec.decorate(selector, forwardMapping, reverseMapping); }