/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.consolidate; import com.github.geophile.erdo.Configuration; import com.github.geophile.erdo.TestFactory; import com.github.geophile.erdo.map.Factory; import com.github.geophile.erdo.transaction.TimestampSet; import com.github.geophile.erdo.transaction.Transaction; import com.github.geophile.erdo.transaction.TransactionManager; import junit.framework.Assert; import org.junit.After; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import static com.github.geophile.erdo.consolidate.Consolidation.Container; import static com.github.geophile.erdo.consolidate.Consolidation.Element; import static org.junit.Assert.fail; // Runs by itself but hangs when run with all tests?!?! @Ignore public class ConsolidationSetTest { @BeforeClass public static void beforeClass() { FACTORY = new TestFactory(); TRANSACTION_MANAGER = FACTORY.transactionManager(); } @After public void after() { FACTORY.reset(); } @Test public void testConsolidation() throws InterruptedException, IOException { // TODO: async commit for (int threads = 1; threads <= 3; threads++) { /* System.out.println(String.format("consolidation threads: %s", threads)); */ Configuration configuration = Configuration.defaultConfiguration(); configuration.consolidationThreads(threads); test(configuration, false); test(configuration, true); } } private void test(Configuration configuration, boolean suppressSmallConsolidations) throws InterruptedException, IOException { /* System.out.println("suppressSmallConsolidations: " + suppressSmallConsolidations); */ this.suppressSmallConsolidations = suppressSmallConsolidations; if (suppressSmallConsolidations) { configuration.consolidationMinSizeBytes(); configuration.consolidationMaxPendingCommittedSizeBytes(0); } else { } reset(); TestContainer owner = new TestContainer(configuration); for (int i = 0; i < N; i++) { /* if (i % 1000 == 0) { System.out.println("add " + i); } */ owner.addElement(new TestElement(list(i))); TRANSACTION_MANAGER.commitTransaction(null, null); } boolean[] check = new boolean[N]; SortedMap<Integer, Integer> sizeCounts = new TreeMap<Integer, Integer>(); for (Element e : owner.consolidationSet.snapshot().elements()) { TestElement element = (TestElement) e; for (Integer x : element.list) { Assert.assertTrue(!check[x]); check[x] = true; } Integer size = element.list.size(); Integer count = sizeCounts.get(size); if (count == null) { count = 1; } else { count += 1; } sizeCounts.put(size, count); } System.out.println(String.format("N: %s, suppressSmallConsolidations: %s - %s", suppressSmallConsolidations, configuration.consolidationThreads(), sizeCounts)); for (boolean b : check) { Assert.assertTrue(b); } int total = 0; for (Map.Entry<Integer, Integer> entry : sizeCounts.entrySet()) { Integer size = entry.getKey(); Integer count = entry.getValue(); total += size * count; } Assert.assertEquals(N, total); owner.stop(); } private void reset() { Transaction.initialize(FACTORY); FACTORY.reset(); } private void print(String template, Object... args) { System.out.println(String.format(template, args)); } private List<Integer> list(Integer... values) { return Arrays.asList(values); } private static final int N = 10000; private static TestFactory FACTORY; private static TransactionManager TRANSACTION_MANAGER; private AtomicInteger idCounter = new AtomicInteger(0); private boolean suppressSmallConsolidations; private class TestElement implements Element { public long id() { return id; } public long count() { return list.size(); } public long sizeBytes() { return suppressSmallConsolidations ? list.size() : 0; } public void destroyPersistentState() { } public void markDurable() { this.durable = true; if (initialTransaction != null) { initialTransaction.markDurable(); } } public boolean durable() { return durable; } public TimestampSet timestamps() { return null; } public void registerTransactions(List<Transaction> transactions) { this.transactions.addAll(transactions); } public List<Transaction> transactions() { return transactions; } public TestElement(List<Integer> list) { this.id = idCounter.getAndIncrement(); this.list = list; this.initialTransaction = TRANSACTION_MANAGER.currentTransaction(); } private final int id; private final List<Integer> list; private final Transaction initialTransaction; private final List<Transaction> transactions = new ArrayList<Transaction>(); private boolean durable = false; } private class TestContainer implements Container { public Configuration configuration() { return consolidationSet.configuration(); } public Element consolidate(List<Element> elements, boolean inputDurable, boolean outputDurable) { TestElement consolidated = new TestElement(new ArrayList<Integer>()); for (Element element : elements) { TestElement r = (TestElement) element; consolidated.list.addAll(r.list); } return consolidated; } public void replaceObsolete(List<Element> obsolete, Element replacement) { } public Factory factory() { return FACTORY; } public void stop() throws InterruptedException, IOException { consolidationSet.shutdown(); } public TestContainer(Configuration configuration) { if (suppressSmallConsolidations) { configuration.consolidationMinSizeBytes((int)(N * 1.1)); } this.consolidationSet = ConsolidationSet.newConsolidationSet(this, Collections.<Element>emptyList()); } public synchronized void addElement(TestElement element) throws InterruptedException, IOException { consolidationSet.add(element, true); } @Override public void reportCrash(Throwable crash) { fail(); } // Object state final ConsolidationSet consolidationSet; } }