jetbrains.exodus.env.EnvironmentTestsBase.java Source code

Java tutorial

Introduction

Here is the source code for jetbrains.exodus.env.EnvironmentTestsBase.java

Source

/**
 * Copyright 2010 - 2015 JetBrains s.r.o.
 *
 * Licensed 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 jetbrains.exodus.env;

import jetbrains.exodus.ByteIterable;
import jetbrains.exodus.ExodusException;
import jetbrains.exodus.TestUtil;
import jetbrains.exodus.bindings.StringBinding;
import jetbrains.exodus.core.dataStructures.Pair;
import jetbrains.exodus.core.execution.Job;
import jetbrains.exodus.core.execution.JobProcessor;
import jetbrains.exodus.core.execution.ThreadJobProcessor;
import jetbrains.exodus.core.execution.locks.Latch;
import jetbrains.exodus.io.DataReader;
import jetbrains.exodus.io.DataWriter;
import jetbrains.exodus.io.FileDataReader;
import jetbrains.exodus.io.FileDataWriter;
import jetbrains.exodus.log.Log;
import jetbrains.exodus.log.LogConfig;
import jetbrains.exodus.log.LoggableFactory;
import jetbrains.exodus.log.RandomAccessLoggable;
import jetbrains.exodus.util.CompressBackupUtil;
import jetbrains.exodus.util.IOUtil;
import jetbrains.exodus.util.TeamCityMessenger;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.zip.GZIPOutputStream;

@SuppressWarnings({ "ProtectedField", "UnusedDeclaration", "CallToPrintStackTrace" })
public class EnvironmentTestsBase {

    private static final String TEAMCITY_MESSAGES = "teamcity.messages";

    protected EnvironmentImpl env;
    private JobProcessor processor;
    private File envDirectory = null;
    protected DataReader reader;
    protected DataWriter writer;
    protected TeamCityMessenger myMessenger = null;

    @Before
    public void setUp() throws Exception {
        Log.invalidateSharedCache();
        final Pair<DataReader, DataWriter> readerWriterPair = createRW();
        reader = readerWriterPair.getFirst();
        writer = readerWriterPair.getSecond();
        LoggableFactory.clear();
        createEnvironment();
        processor = new ThreadJobProcessor("EnvironmentTestsBase processor");
        processor.start();
        String tcMsgFileName = System.getProperty(TEAMCITY_MESSAGES);
        if (tcMsgFileName != null) {
            try {
                myMessenger = new TeamCityMessenger(tcMsgFileName);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("TeamCity messages disabled   :   no file to write messages in");
        }
    }

    @After
    public void tearDown() throws Exception {
        try {
            if (env != null) {
                env.close();
            }
        } catch (final ExodusException e) {
            archiveDB(env.getLocation(), getClass().getName() + '.' + System.currentTimeMillis() + ".tar.gz");
            throw e;
        } finally {
            Log.invalidateSharedCache();
            deleteRW();
            processor.finish();
            if (myMessenger != null) {
                myMessenger.close();
            }
        }
    }

    public static void archiveDB(final String location, final String target) {
        try {
            System.out.println("Dumping " + location + " to " + target);
            final File root = new File(location);
            final File targetFile = new File(target);
            TarArchiveOutputStream tarGz = new TarArchiveOutputStream(
                    new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(targetFile)), 0x1000));
            for (final File file : IOUtil.listFiles(root)) {
                final long fileSize = file.length();
                if (file.isFile() && fileSize != 0) {
                    CompressBackupUtil.archiveFile(tarGz, "", file, fileSize);
                }
            }
            tarGz.close();
        } catch (IOException ioe) {
            System.out.println("Can't create backup");
        }
    }

    protected EnvironmentImpl getEnvironment() {
        return env;
    }

    protected EnvironmentImpl newEnvironmentInstance(final LogConfig config) {
        return (EnvironmentImpl) Environments.newInstance(config);
    }

    protected EnvironmentImpl newEnvironmentInstance(final LogConfig config, final EnvironmentConfig ec) {
        return (EnvironmentImpl) Environments.newInstance(config, ec);
    }

    protected EnvironmentImpl newContextualEnvironmentInstance(final LogConfig config) {
        return newContextualEnvironmentInstance(config, new EnvironmentConfig());
    }

    protected EnvironmentImpl newContextualEnvironmentInstance(final LogConfig config, final EnvironmentConfig ec) {
        return (EnvironmentImpl) Environments.newContextualInstance(config, ec);
    }

    protected void createEnvironment() {
        env = newEnvironmentInstance(LogConfig.create(reader, writer));
    }

    protected Log getLog() {
        return env.getLog();
    }

    protected Pair<DataReader, DataWriter> createRW() throws IOException {
        final File testsDirectory = getEnvDirectory();
        if (testsDirectory.exists()) {
            IOUtil.deleteRecursively(testsDirectory);
        } else if (!testsDirectory.mkdir()) {
            throw new IOException("Failed to create directory for tests.");
        }
        return new Pair<DataReader, DataWriter>(new FileDataReader(testsDirectory, 16),
                new FileDataWriter(testsDirectory));
    }

    protected void deleteRW() {
        final File testsDirectory = getEnvDirectory();
        IOUtil.deleteRecursively(testsDirectory);
        IOUtil.deleteFile(testsDirectory);
        envDirectory = null;
        reader = null;
        writer = null;
    }

    protected File getEnvDirectory() {
        if (envDirectory == null) {
            envDirectory = TestUtil.createTempDir();
        }
        return envDirectory;
    }

    protected void executeParallelTransaction(@NotNull final TransactionalExecutable runnable) {
        try {
            final Latch sync = Latch.create();
            sync.acquire();
            processor.queue(new Job() {
                @Override
                protected void execute() throws Throwable {
                    env.executeInTransaction(runnable);
                    sync.release();
                }
            });
            sync.acquire();
        } catch (InterruptedException e) {
            // ignore
        }
    }

    protected void runParallelRunnable(@NotNull final Runnable runnable) {
        processor.queue(new Job() {
            @Override
            protected void execute() throws Throwable {
                runnable.run();
            }
        });
    }

    protected Store openStoreAutoCommit(final String name, final StoreConfig config) {
        return env.computeInTransaction(new TransactionalComputable<Store>() {
            @Override
            public Store compute(@NotNull Transaction txn) {
                return env.openStore(name, config, txn);
            }
        });
    }

    protected void putAutoCommit(@NotNull final Store store, @NotNull final ByteIterable key,
            @NotNull final ByteIterable value) {
        env.executeInTransaction(new TransactionalExecutable() {
            @Override
            public void execute(@NotNull final Transaction txn) {
                store.put(txn, key, value);
            }
        });
    }

    protected ByteIterable getAutoCommit(@NotNull final Store store, @NotNull final ByteIterable key) {
        return env.computeInReadonlyTransaction(new TransactionalComputable<ByteIterable>() {
            @Override
            public ByteIterable compute(@NotNull Transaction txn) {
                return store.get(txn, key);
            }
        });
    }

    protected boolean deleteAutoCommit(@NotNull final Store store, @NotNull final ByteIterable key) {
        return env.computeInTransaction(new TransactionalComputable<Boolean>() {
            @Override
            public Boolean compute(@NotNull Transaction txn) {
                return store.delete(txn, key);
            }
        });
    }

    protected long countAutoCommit(@NotNull final Store store) {
        return env.computeInTransaction(new TransactionalComputable<Long>() {
            @Override
            public Long compute(@NotNull Transaction txn) {
                return store.count(txn);
            }
        });
    }

    protected static void assertLoggableTypes(final Iterator<RandomAccessLoggable> it, final int... types) {
        assertLoggableTypes(Integer.MAX_VALUE, it, types);
    }

    protected static void assertLoggableTypes(final Log log, final int address, final int... types) {
        assertLoggableTypes(Integer.MAX_VALUE, log.getLoggableIterator(address), types);
    }

    protected static void assertLoggableTypes(final int max, final Iterator<RandomAccessLoggable> it,
            final int... types) {
        int i = 0;
        for (int type : types) {
            if (++i > max) {
                break;
            }
            Assert.assertTrue(it.hasNext());
            Assert.assertEquals(type, it.next().getType());
        }
        Assert.assertFalse(it.hasNext());
    }

    protected void assertNotNullStringValue(final Store store, final ByteIterable keyEntry, final String value) {
        env.executeInTransaction(new TransactionalExecutable() {
            @Override
            public void execute(@NotNull Transaction txn) {
                assertNotNullStringValue(txn, store, keyEntry, value);
            }
        });
    }

    protected void assertNotNullStringValue(final Transaction txn, final Store store, final ByteIterable keyEntry,
            final String value) {
        final ByteIterable valueEntry = store.get(txn, keyEntry);
        Assert.assertNotNull(valueEntry);
        Assert.assertEquals(value, StringBinding.entryToString(valueEntry));
    }

    protected void assertEmptyValue(final Store store, final ByteIterable keyEntry) {
        env.executeInTransaction(new TransactionalExecutable() {
            @Override
            public void execute(@NotNull Transaction txn) {
                assertEmptyValue(txn, store, keyEntry);
            }
        });
    }

    protected void assertEmptyValue(final Transaction txn, final Store store, final ByteIterable keyEntry) {
        final ByteIterable valueEntry = store.get(txn, keyEntry);
        Assert.assertNull(valueEntry);
    }

    protected void assertNotNullStringValues(final Store store, final String... values) {
        env.executeInTransaction(new TransactionalExecutable() {
            @Override
            public void execute(@NotNull Transaction txn) {
                try (Cursor cursor = store.openCursor(txn)) {
                    int i = 0;
                    while (cursor.getNext()) {
                        final ByteIterable valueEntry = cursor.getValue();
                        Assert.assertNotNull(valueEntry);
                        final String value = values[i++];
                        Assert.assertEquals(value, StringBinding.entryToString(valueEntry));
                    }
                }
            }
        });
    }

    protected void reopenEnvironment() {
        final EnvironmentConfig envConfig = env.getEnvironmentConfig();
        env.close();
        env = newEnvironmentInstance(LogConfig.create(reader, writer), envConfig);
    }

    protected void setLogFileSize(int kilobytes) {
        final EnvironmentConfig envConfig = env.getEnvironmentConfig();
        if (envConfig.getLogCachePageSize() > kilobytes * 1024) {
            envConfig.setLogCachePageSize(kilobytes * 1024);
        }
        envConfig.setLogFileSize(kilobytes);
        Log.invalidateSharedCache();
        reopenEnvironment();
    }

    protected void set1KbFileWithoutGC() {
        setLogFileSize(1);
        env.getEnvironmentConfig().setGcEnabled(false);
    }

    protected void set2KbFileWithoutGC() {
        setLogFileSize(2);
        env.getEnvironmentConfig().setGcEnabled(false);
    }
}