All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.vyarus.guice.persist.orient.db.DatabaseManager Maven / Gradle / Ivy

There is a newer version: 4.1.0
Show newest version
package ru.vyarus.guice.persist.orient.db;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.persist.PersistService;
import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.tx.OTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.vyarus.guice.persist.orient.db.data.DataInitializer;
import ru.vyarus.guice.persist.orient.db.pool.PoolManager;
import ru.vyarus.guice.persist.orient.db.scheme.SchemeInitializationException;
import ru.vyarus.guice.persist.orient.db.scheme.SchemeInitializer;
import ru.vyarus.guice.persist.orient.db.transaction.TxConfig;
import ru.vyarus.guice.persist.orient.db.transaction.template.TxAction;
import ru.vyarus.guice.persist.orient.db.transaction.template.TxTemplate;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
 * Responsible for database lifecycle. Creates db if necessary and call schema and data initializers
 * for just opened database. Also, responsible for pools lifecycle.
 *
 * @author Vyacheslav Rusakov
 * @see ru.vyarus.guice.persist.orient.db.scheme.SchemeInitializer
 * @see ru.vyarus.guice.persist.orient.db.data.DataInitializer
 * @since 24.07.2014
 */
@Singleton
public class DatabaseManager implements PersistService {
    private final Logger logger = LoggerFactory.getLogger(DatabaseManager.class);

    private final String uri;
    private final boolean autoCreate;

    private final List pools;
    private final SchemeInitializer modelInitializer;
    private final DataInitializer dataInitializer;
    private final TxTemplate txTemplate;

    // used to allow multiple start/stop calls (could be if service managed directly and PersistFilter registered)
    private boolean initialized;
    private Set supportedTypes;

    @Inject
    public DatabaseManager(
            @Named("orient.uri") final String uri,
            @Named("orient.db.autocreate") final boolean autoCreate,
            final Set pools,
            final SchemeInitializer modelInitializer,
            final DataInitializer dataInitializer,
            final TxTemplate txTemplate) {

        this.uri = Preconditions.checkNotNull(uri, "Database name required");
        this.autoCreate = autoCreate;
        this.pools = Lists.newArrayList(pools);
        this.modelInitializer = modelInitializer;
        this.dataInitializer = dataInitializer;
        this.txTemplate = txTemplate;
        // sort pools to correct startup order
        Collections.sort(this.pools, new Comparator() {
            @Override
            public int compare(final PoolManager o1, final PoolManager o2) {
                return o1.getType().compareTo(o2.getType());
            }
        });
    }

    @Override
    public void start() {
        if (initialized) {
            logger.warn("Duplicate initialization prevented. Check your initialization logic: "
                    + "persistent service should not be started two or more times");
            return;
        }

        createIfRequired();
        startPools();
        logger.debug("Registered types: {}", supportedTypes);
        logger.debug("Initializing database: '{}'", uri);
        // no tx (because of schema update - orient requirement)
        try {
            txTemplate.doInTransaction(new TxConfig(OTransaction.TXTYPE.NOTX), new TxAction() {
                @Override
                public Void execute() throws Throwable {
                    modelInitializer.initialize();
                    return null;
                }
            });
        } catch (Throwable throwable) {
            throw new SchemeInitializationException("Failed to initialize scheme", throwable);
        }

        // db ready to work
        initialized = true;
        // tx may be enabled (it's up to implementer)
        dataInitializer.initializeData();
    }

    @Override
    public void stop() {
        if (!initialized) {
            // prevent double stop
            return;
        }
        initialized = false;
        stopPools();
    }

    /**
     * @return set of supported database types (according to registered pools)
     */
    public Set getSupportedTypes() {
        return ImmutableSet.copyOf(supportedTypes);
    }

    /**
     * @param type db type to check
     * @return true if db tpe supported (supporting pool registered), false otherwise
     */
    public boolean isTypeSupported(final DbType type) {
        return supportedTypes.contains(type);
    }

    protected void createIfRequired() {
        // create if required (without creation work with db is impossible)
        // memory, local, plocal modes support simplified db creation,
        // but remote database must be created differently
        if (autoCreate && isLocalDatabase()) {
            final ODatabaseDocumentTx database = new ODatabaseDocumentTx(uri);
            try {
                if (!database.exists()) {
                    logger.info("Creating database: '{}'", uri);
                    database.create();
                }
            } finally {
                database.close();
            }
        }
    }

    /**
     * @return true if database is local, false for remote
     */
    private boolean isLocalDatabase() {
        return !this.uri.startsWith("remote:");
    }

    protected void startPools() {
        supportedTypes = Sets.newHashSet();
        for (PoolManager pool : pools) {
            // if pool start failed, entire app start should fail (no catch here)
            pool.start(uri);
            supportedTypes.add(Preconditions.checkNotNull(pool.getType(),
                    "Pool %s doesn't declare correct pool type", pool.getClass().getSimpleName()));
        }
    }

    protected void stopPools() {
        for (PoolManager pool : pools) {
            try {
                pool.stop();
            } catch (Throwable ex) {
                // continue to properly shutdown all pools
                logger.error("Pool '" + pool.getType() + "' shutdown failed (" + pool.getClass() + ")", ex);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy