@Test public void shouldProvideIndexStatisticsWhenIndexIsBuiltViaPopulationAndConcurrentAdditionsAndDeletions() throws Exception { // given some initial data long[] nodes = repeatCreateNamedPeopleFor(NAMES.length * CREATION_MULTIPLIER); int initialNodes = nodes.length; // when populating while creating IndexDescriptor index = createIndex("Person", "name"); UpdatesTracker updatesTracker = executeCreationsAndDeletions(nodes, index, CREATION_MULTIPLIER); awaitOnline(index); // then int seenWhilePopulating = initialNodes + updatesTracker.createdDuringPopulation() - updatesTracker.deletedDuringPopulation(); double expectedSelectivity = UNIQUE_NAMES / (seenWhilePopulating); assertCorrectIndexSelectivity(expectedSelectivity, indexSelectivity(index)); assertCorrectIndexSize(seenWhilePopulating, indexSize(index)); int expectedIndexUpdates = updatesTracker.deletedAfterPopulation() + updatesTracker.createdAfterPopulation(); assertCorrectIndexUpdates(expectedIndexUpdates, indexUpdates(index)); }
@Test public void shouldWorkWhileHavingHeavyConcurrentUpdates() throws Exception { // given some initial data final long[] nodes = repeatCreateNamedPeopleFor(NAMES.length * CREATION_MULTIPLIER); int initialNodes = nodes.length; int threads = 5; ExecutorService executorService = Executors.newFixedThreadPool(threads); // when populating while creating final IndexDescriptor index = createIndex("Person", "name"); final Collection<Callable<UpdatesTracker>> jobs = new ArrayList<>(threads); for (int i = 0; i < threads; i++) { jobs.add( new Callable<UpdatesTracker>() { @Override public UpdatesTracker call() throws Exception { return executeCreationsDeletionsAndUpdates(nodes, index, CREATION_MULTIPLIER); } }); } List<Future<UpdatesTracker>> futures = executorService.invokeAll(jobs); // sum result into empty result UpdatesTracker result = new UpdatesTracker(); result.notifyPopulationCompleted(); for (Future<UpdatesTracker> future : futures) { result.add(future.get()); } awaitOnline(index); executorService.awaitTermination(1, TimeUnit.SECONDS); executorService.shutdown(); // then int tolerance = MISSED_UPDATES_TOLERANCE * threads; double doubleTolerance = DOUBLE_ERROR_TOLERANCE * threads; int seenWhilePopulating = initialNodes + result.createdDuringPopulation() - result.deletedDuringPopulation(); double expectedSelectivity = UNIQUE_NAMES / (seenWhilePopulating); assertCorrectIndexSelectivity(expectedSelectivity, indexSelectivity(index), doubleTolerance); assertCorrectIndexSize( "Tracker had " + result, seenWhilePopulating, indexSize(index), tolerance); int expectedIndexUpdates = result.deletedAfterPopulation() + result.createdAfterPopulation(); assertCorrectIndexUpdates( "Tracker had " + result, expectedIndexUpdates, indexUpdates(index), tolerance); }