package com.tesora.dve.sql.statement.ddl; /* * #%L * Tesora Inc. * Database Virtualization Engine * %% * Copyright (C) 2011 - 2014 Tesora Inc. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.ArrayList; import java.util.List; import com.tesora.dve.common.MultiMap; import com.tesora.dve.common.catalog.PersistentGroup; import com.tesora.dve.db.DBEmptyTextResultConsumer; import com.tesora.dve.db.DBResultConsumer; import com.tesora.dve.exceptions.PEException; import com.tesora.dve.queryplan.ExecutionState; import com.tesora.dve.queryplan.QueryStepRebalance; import com.tesora.dve.queryplan.QueryStepDDLNestedOperation.NestedOperationDDLCallback; import com.tesora.dve.server.connectionmanager.SSConnection; import com.tesora.dve.sql.schema.PEAbstractTable; import com.tesora.dve.sql.schema.PEDatabase; import com.tesora.dve.sql.schema.PEPersistentGroup; import com.tesora.dve.sql.schema.PETable; import com.tesora.dve.sql.schema.PEViewTable; import com.tesora.dve.sql.schema.Persistable; import com.tesora.dve.sql.schema.RangeDistribution; import com.tesora.dve.sql.schema.RangeDistributionVector; import com.tesora.dve.sql.schema.SchemaContext; import com.tesora.dve.sql.schema.cache.CacheInvalidationRecord; import com.tesora.dve.sql.transform.behaviors.BehaviorConfiguration; import com.tesora.dve.sql.transform.execution.ComplexDDLExecutionStep; import com.tesora.dve.sql.transform.execution.ExecutionSequence; import com.tesora.dve.sql.transform.execution.CatalogModificationExecutionStep.Action; import com.tesora.dve.sql.util.ListSet; import com.tesora.dve.sql.util.Pair; import com.tesora.dve.worker.WorkerGroup; public class StartRebalanceStatement extends DDLStatement { PEPersistentGroup onGroup; public StartRebalanceStatement(PEPersistentGroup grp) { super(true); this.onGroup = grp; } @Override public Action getAction() { return Action.ALTER; } @Override public Persistable<?, ?> getRoot() { // no root as yet return null; } @Override public CacheInvalidationRecord getInvalidationRecord(SchemaContext sc) { return CacheInvalidationRecord.GLOBAL; } @Override public void plan(SchemaContext sc, ExecutionSequence es, BehaviorConfiguration config) throws PEException { MultiMap<PEDatabase,PETable> plain = new MultiMap<PEDatabase,PETable>(); MultiMap<PEDatabase,PETable> fks = new MultiMap<PEDatabase,PETable>(); MultiMap<PEDatabase,PEViewTable> views = new MultiMap<PEDatabase,PEViewTable>(); AddStorageSiteStatement.sortTablesOnGroup(sc,onGroup,plain,fks,views); ListSet<PEDatabase> dbs = new ListSet<PEDatabase>(); dbs.addAll(views.keySet()); dbs.addAll(plain.keySet()); dbs.addAll(fks.keySet()); Pair<List<PEAbstractTable<?>>,Boolean> tableDeclOrder = AddStorageSiteStatement.buildTableDeclOrder(sc,plain,fks); MultiMap<RangeDistribution,PETable> tablesByRange = new MultiMap<RangeDistribution,PETable>(); for(PEAbstractTable<?> abst : tableDeclOrder.getFirst()) { if (abst.isView()) continue; PETable pet = abst.asTable(); if (pet.getDistributionVector(sc).isRange()) { RangeDistributionVector rdv = (RangeDistributionVector) pet.getDistributionVector(sc); tablesByRange.put(rdv.getRangeDistribution().getDistribution(sc),pet); } } List<AddStorageGenRangeInfo> rangeInfo = buildRangeInfo(sc,tablesByRange); /* for(AddStorageGenRangeInfo info : rangeInfo) { info.display(System.out); } */ es.append(new ComplexDDLExecutionStep(null,onGroup,null,Action.ALTER, new RebalanceCallback(onGroup,rangeInfo,tableDeclOrder.getSecond()))); } private List<AddStorageGenRangeInfo> buildRangeInfo(SchemaContext sc, MultiMap<RangeDistribution,PETable> tablesByRange) { List<AddStorageGenRangeInfo> out = new ArrayList<AddStorageGenRangeInfo>(); for(RangeDistribution rd : tablesByRange.keySet()) out.add(new AddStorageGenRangeInfo(sc,rd,(List<PETable>) tablesByRange.get(rd))); return out; } private static class RebalanceCallback extends NestedOperationDDLCallback { private final List<AddStorageGenRangeInfo> rangeInfo; private final PEPersistentGroup onGroup; private final boolean ignoreFKS; public RebalanceCallback(PEPersistentGroup onGroup, List<AddStorageGenRangeInfo> rangeInfo, boolean ignoreFKS) { this.onGroup = onGroup; this.rangeInfo = rangeInfo; this.ignoreFKS = ignoreFKS; } @Override public void executeNested(ExecutionState estate, WorkerGroup wg, DBResultConsumer resultConsumer) throws Throwable { SSConnection conn = estate.getConnection(); SchemaContext cntxt = conn.getSchemaContext(); cntxt.beginSaveContext(); PersistentGroup pg = null; try { pg = onGroup.persistTree(cntxt); } finally { cntxt.endSaveContext(); } QueryStepRebalance rangeRebalance = new QueryStepRebalance(pg,rangeInfo,ignoreFKS); rangeRebalance.executeSelf(estate, wg, DBEmptyTextResultConsumer.INSTANCE); } @Override public String description() { return "rebalance operation"; } @Override public CacheInvalidationRecord getInvalidationRecord() { return CacheInvalidationRecord.GLOBAL; } } }