Package edu.brown.catalog.special

Source Code of edu.brown.catalog.special.VerticalPartitionColumn

package edu.brown.catalog.special;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.MaterializedViewInfo;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Statement;
import org.voltdb.catalog.Table;
import org.voltdb.compiler.VoltCompiler;
import org.voltdb.planner.VerticalPartitionPlanner;

import edu.brown.catalog.CatalogUtil;
import edu.brown.logging.LoggerUtil;
import edu.brown.logging.LoggerUtil.LoggerBoolean;
import edu.brown.utils.StringUtil;

public class VerticalPartitionColumn extends MultiColumn {
    private static final Logger LOG = Logger.getLogger(VerticalPartitionColumn.class);
    private static final LoggerBoolean debug = new LoggerBoolean();
    private static final LoggerBoolean trace = new LoggerBoolean();
    static {
        LoggerUtil.attachObserver(LOG, debug, trace);
    }

    public static final String PREFIX = "*VerticalPartitionColumn*";

    private transient final Map<Statement, Statement> optimized = new HashMap<Statement, Statement>();
    private transient final Map<Statement, Statement> backups = new HashMap<Statement, Statement>();
    private transient boolean applied = false;
    private transient MaterializedViewInfo catalog_view;

    /**
     * THIS SHOULD NOT BE CALLED DIRECTLY Use VerticalPartitionColumn.get()
     *
     * @param attributes
     */
    public VerticalPartitionColumn(Collection<Column> attributes) {
        super((Collection<? extends Column>) attributes);

        // There should only be two elements
        // The first one is the horizontal partitioning parameter(s)
        // The second one is the vertical partitioning parameter(s)
        assert (attributes.size() == 2) : "Total # of Attributes = " + this.getSize() + ": " + StringUtil.join(",", this);
    }

    public static VerticalPartitionColumn get(Column hp_cols, MultiColumn vp_cols) {
        assert (vp_cols.size() > 0) : "Empty vertical partitioning columns";
        return InnerMultiAttributeCatalogType.get(VerticalPartitionColumn.class, hp_cols, (Column) vp_cols);
    }

    // --------------------------------------------------------------------------------------------
    // UTILITY METHODS
    // --------------------------------------------------------------------------------------------

    @Override
    public String toString() {
        Map<String, Object> m = new LinkedHashMap<String, Object>();
        m.put("Horizontal", CatalogUtil.debug(this.getHorizontalColumn()));
        m.put("Vertical", CatalogUtil.debug(this.getVerticalPartitionColumns()));

        Map<String, String> inner = new HashMap<String, String>();
        for (Entry<Statement, Statement> e : this.optimized.entrySet()) {
            inner.put(e.getKey().fullName(), e.getValue().fullName());
        } // FOR
        m.put("Optimized Queries", inner);

        return StringUtil.formatMaps(m);
    }

    @Override
    public String getPrefix() {
        return (PREFIX);
    }

    @Override
    public void clear() {
        this.catalog_view = null;
        this.applied = false;
        this.optimized.clear();
        this.backups.clear();
    }

    public Collection<Statement> getOptimizedQueries() {
        return (this.optimized.keySet());
    }

    public Statement getOptimizedQuery(Statement catalog_stmt) {
        return (this.optimized.get(catalog_stmt));
    }

    public void addOptimizedQueries(Map<Statement, Statement> queries) {
        this.optimized.putAll(queries);
    }

    public boolean hasOptimizedQueries() {
        return (this.optimized.size() > 0);
    }

    /**
     * Return the Horizontal Partitioning Column
     *
     * @return
     */
    public Column getHorizontalColumn() {
        return (this.get(0));
    }

    /**
     * Return the Vertical Partitioning Columns
     *
     * @return
     */
    public Collection<Column> getVerticalPartitionColumns() {
        return ((MultiColumn) this.get(1)).getAttributes();
    }

    public MultiColumn getVerticalMultiColumn() {
        return ((MultiColumn) this.get(1));
    }

    public List<String> getVerticalPartitionColumnNames() {
        List<String> columnNames = new ArrayList<String>();
        for (Column catalog_col : this.getVerticalPartitionColumns()) {
            columnNames.add(catalog_col.getName());
        } // FOR
        return (columnNames);
    }

    /**
     * Returns true if we have vertical partition columns defined
     *
     * @return
     */
    public boolean hasVerticalPartitionColumns() {
        Collection<Column> cols = this.getVerticalPartitionColumns();
        return (cols != null && cols.size() > 0);
    }

    public MaterializedViewInfo getViewCatalog() {
        return (this.catalog_view);
    }

    // --------------------------------------------------------------------------------------------
    // CATALOG UPDATING METHODS
    // --------------------------------------------------------------------------------------------

    /**
     * Returns true if updateCatalog() has been called and the Statements now
     * have the optimized query plans applied
     */
    public boolean isUpdateApplied() {
        return (this.applied);
    }

    public synchronized MaterializedViewInfo createMaterializedView() {
        Table catalog_tbl = this.getParent();
        MaterializedViewInfo catalog_view = CatalogUtil.getVerticalPartition(catalog_tbl);
        if (catalog_view == null || catalog_view.getDest() == null) {
            Collection<Column> cols = this.getVerticalPartitionColumns();
            assert (cols.size() > 0) : "No Vertical Partition columns for " + this;
            if (trace.val)
                LOG.trace("Creating VerticalPartition in catalog for " + catalog_tbl + ": " + cols);
            try {
                catalog_view = VoltCompiler.addVerticalPartition(catalog_tbl, cols, true);
                assert (catalog_view != null);
            } catch (Throwable ex) {
                throw new RuntimeException("Failed to create vertical partition for " + this, ex);
            }
            if (debug.val)
                LOG.debug(String.format("Created vertical partition %s.%s: %s", catalog_tbl.getName(), catalog_view.getName(), CatalogUtil.debug(catalog_view.getDest().getColumns())));

        } else if (debug.val) {
            LOG.debug(String.format("Using existing vertical partition %s.%s: %s", catalog_tbl.getName(), catalog_view.getName(), CatalogUtil.debug(catalog_view.getDest().getColumns())));
        }
        validate(catalog_view, catalog_tbl);
        return (catalog_view);
    }

    /**
     * Create the MaterializedView catalog object for this vertical partition
     * candidate
     */
    public MaterializedViewInfo applyUpdate() {
        assert (this.applied == false) : "Trying to apply " + this + " more than once";
        Table catalog_tbl = this.getParent();
        assert (catalog_tbl != null);

        if (this.catalog_view == null) {
            this.catalog_view = this.createMaterializedView();
        } else {
            if (debug.val)
                LOG.debug("Reusing existing vertical partition " + this.catalog_view + " for " + catalog_tbl);
            if (catalog_tbl.getViews().contains(catalog_view) == false)
                catalog_tbl.getViews().add(this.catalog_view, false);
        }
        assert (this.catalog_view != null);

        // Make sure that the view's destination table is in the catalog
        Database catalog_db = CatalogUtil.getDatabase(catalog_view);
        if (catalog_db.getTables().contains(catalog_view.getDest()) == false) {
            if (debug.val)
                LOG.debug("Adding back " + catalog_view.getDest() + " to catalog");
            catalog_db.getTables().add(catalog_view.getDest(), false);
        } else if (debug.val) {
            LOG.debug(String.format("%s already exists in catalog %s", catalog_view.getDest(), catalog_db.getTables()));
        }

        // Apply the new Statement query plans
        if (debug.val && this.optimized.isEmpty()) {
            LOG.warn("There are no optimized query plans for " + this.fullName());
        }
        for (Entry<Statement, Statement> e : this.optimized.entrySet()) {
            // Make a back-up for each original Statement
            Statement backup = this.backups.get(e.getKey());
            if (backup == null) {
                Procedure catalog_proc = e.getKey().getParent();
                backup = catalog_proc.getStatements().add("BACKUP__" + e.getKey().getName());
                if (debug.val)
                    LOG.debug(String.format("Created temporary catalog object %s to back-up %s's query plans", backup.getName(), e.getKey().fullName()));
                this.backups.put(e.getKey(), backup);
                boolean ret = catalog_proc.getStatements().remove(backup);
                assert (ret);
                assert (catalog_proc.getStatements().contains(backup) == false);
            }
            VerticalPartitionPlanner.applyOptimization(e.getKey(), backup);

            // Then copy the optimized query plans
            if (debug.val)
                LOG.debug(String.format("Copying optimized query plans from %s to %s", e.getValue().fullName(), e.getKey().fullName()));
            CatalogUtil.copyQueryPlans(e.getValue(), e.getKey());
        } // FOR
        this.applied = true;

        validate(catalog_view, catalog_tbl);

        if (debug.val)
            LOG.debug("Added " + catalog_view.getDest() + " for " + catalog_tbl + " and updated " + this.optimized.size() + " query plans");
        return (this.catalog_view);
    }

    /**
     *
     */
    public void revertUpdate() {
        assert (this.catalog_view != null);
        assert (this.applied) : "Trying to undo " + this + " before applying";

        Table catalog_tbl = this.getParent();
        assert (catalog_tbl != null);
        if (debug.val)
            LOG.debug(String.format("Reverting catalog update on %s for %s", catalog_tbl, this.catalog_view));
        assert (catalog_tbl.getViews().contains(this.catalog_view));
        catalog_tbl.getViews().remove(this.catalog_view);

        // Restore the original query plans from the backups
        for (Statement catalog_stmt : this.optimized.keySet()) {
            Statement backup = this.backups.get(catalog_stmt);
            assert (backup != null) : "Missing backup for " + catalog_stmt.fullName();
            if (debug.val)
                LOG.debug(String.format("Restoring %s's original query plans from %s", catalog_stmt.fullName(), backup.getName()));
            CatalogUtil.copyQueryPlans(backup, catalog_stmt);
        } // FOR
        this.applied = false;

        validate(catalog_view, catalog_tbl);
    }

    private static void validate(MaterializedViewInfo catalog_view, Table catalog_tbl) {
        Database catalog_db = CatalogUtil.getDatabase(catalog_tbl);
        assert (catalog_view.getVerticalpartition());
        assert (catalog_view.getDest() != null) : String.format("MaterializedViewInfo %s for %s is missing destination table!", catalog_view.fullName(), catalog_tbl);
        assert (catalog_db.getTables().contains(catalog_view.getDest())) : String.format("MaterializedViewInfo %s for %s is missing destination table! %s", catalog_view.fullName(), catalog_tbl,
                catalog_db.getTables());
        assert (catalog_view.getGroupbycols().isEmpty() == false) : String.format("MaterializedViewInfo %s for %s is missing groupby columns!", catalog_view.fullName(), catalog_tbl);
        assert (catalog_view.getDest().getColumns().isEmpty() == false) : String.format("MaterializedViewInfo %s for %s is missing virtual columns!", catalog_view.getDest(), catalog_tbl);
        assert (catalog_view.getParent().equals(catalog_tbl)) : String.format("MaterializedViewInfo %s has parent %s, but it should be %s!", catalog_view.fullName(), catalog_view.getParent(),
                catalog_tbl);

    }
}
TOP

Related Classes of edu.brown.catalog.special.VerticalPartitionColumn

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.