/* * 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.systemtest.lockmanagement; import com.github.geophile.erdo.*; import com.github.geophile.erdo.util.FileUtil; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class ErdoTransactionTest { public static void main(String[] args) throws InterruptedException, IOException, DeadlockException, TransactionRolledBackException { new ErdoTransactionTest(args).run(); } private ErdoTransactionTest(String[] args) throws IOException, InterruptedException { // Database setup final File DB_DIRECTORY = new File(FileUtil.tempDirectory(), DB_NAME); FileUtil.deleteDirectory(DB_DIRECTORY); db = Database.createDatabase(DB_DIRECTORY, configuration()); accounts = db.createMap(MAP_NAME, RecordFactory.simpleRecordFactory(AccountId.class, Account.class)); int a = 0; this.nAccounts = Integer.parseInt(args[a++]); this.threads = new ErdoTestThread[Integer.parseInt(args[a++])]; this.transactionsPerThread = Integer.parseInt(args[a++]); LOG.log(Level.INFO, "accounts: {0}", nAccounts); LOG.log(Level.INFO, "threads: {0}", threads.length); LOG.log(Level.INFO, "transactions per thread: {0}", transactionsPerThread); } private void run() throws InterruptedException, IOException, DeadlockException, TransactionRolledBackException { createAccounts(); createThreads(); startThreads(); waitForCompletion(); flush(); verify(); shutdown(); } private void createAccounts() throws IOException, DeadlockException, InterruptedException, TransactionRolledBackException { for (int a = 0; a < nAccounts; a++) { Account account = new Account(new AccountId(a)); account.balance(0); accounts.ensurePresent(account); } db.commitTransaction(); } private void createThreads() { for (int t = 0; t < threads.length; t++) { threads[t] = new ErdoTestThread(t, db, accounts, transactionsPerThread, nAccounts); } } private void startThreads() { for (ErdoTestThread thread : threads) { thread.start(); } } private void waitForCompletion() throws InterruptedException { for (ErdoTestThread thread : threads) { thread.join(); } LOG.log(Level.INFO, "Test threads have all exited."); } private void flush() throws IOException, InterruptedException { db.flush(); } private void verify() throws IOException, InterruptedException { long sum = 0; Cursor cursor = accounts.first(); Account account; while ((account = (Account) cursor.next()) != null) { LOG.log(Level.INFO, "{0}", account); sum += account.balance(); } db.commitTransaction(); if (sum == 0) { LOG.log(Level.INFO, "OK!"); } else { LOG.log(Level.WARNING, "Test failed, sum = {0}", sum); } } private void shutdown() throws IOException, InterruptedException { LOG.log(Level.INFO, "Shutting down"); db.close(); } private Configuration configuration() { Configuration configuration = Configuration.defaultConfiguration(); configuration.consolidationThreads(5); configuration.consolidationMinSizeBytes(4 * (1 << 20)); // 4M configuration.diskSegmentSizeBytes(4 * (1 << 20)); // 4M configuration.diskPageSizeBytes(32 * 1024); // 32K configuration.consolidationMaxPendingCommittedSizeBytes(20 * (1 << 20)); // 20 meg return configuration; } private static final Logger LOG = Logger.getLogger(ErdoTransactionTest.class.getName()); private static final String DB_NAME = "erdo"; private static final String MAP_NAME = "account"; private final Database db; private final int nAccounts; private final OrderedMap accounts; private final ErdoTestThread[] threads; private final int transactionsPerThread; }