package com.tesora.dve.sql.transform.strategy;
/*
* #%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.catalog.PersistentGroup;
import com.tesora.dve.common.catalog.StorageGroup;
import com.tesora.dve.common.catalog.StorageGroup.GroupScale;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.schema.ConnectionValues;
import com.tesora.dve.sql.schema.PEDynamicGroup;
import com.tesora.dve.sql.schema.PEPersistentGroup;
import com.tesora.dve.sql.schema.PEStorageGroup;
import com.tesora.dve.sql.schema.SchemaContext;
public class TempGroupManager {
protected TempGroupPlaceholder aggGroup;
protected List<TempGroupPlaceholder> dynGroup;
// a storage group can be pegged to be the persistent group
protected PEStorageGroup pegged;
public TempGroupManager() {
aggGroup = new TempGroupPlaceholder(true);
dynGroup = new ArrayList<TempGroupManager.TempGroupPlaceholder>();
}
public void pegGroup(PEPersistentGroup p) {
if (pegged != null && !(pegged instanceof PEPersistentGroup))
throw new SchemaException(Pass.PLANNER, "Attempt to peg temp group to transient group");
pegged = p;
}
public TempGroupPlaceholder getGroup(boolean agg) {
return aggGroup;
}
public TempGroupPlaceholder getGroup(int cost) throws PEException {
TempGroupPlaceholder tgph = new TempGroupPlaceholder(cost);
dynGroup.add(tgph);
return tgph;
}
public TempGroupPlaceholder getLatestGroup(int cost) throws PEException {
if (dynGroup.size() > 0) {
TempGroupPlaceholder tgph = dynGroup.get(dynGroup.size()-1);
if (tgph.getCost() < cost) {
tgph.setCost(cost);
}
return tgph;
}
return getGroup(cost);
}
public void plan(SchemaContext context) throws PEException {
if (pegged != null) {
for(TempGroupPlaceholder tgph : dynGroup) {
tgph.setBacking(context, pegged);
}
aggGroup.setBacking(context, pegged.anySite(context));
} else {
for(TempGroupPlaceholder tgph : dynGroup) {
tgph.createBacking(context);
}
aggGroup.createBacking(context);
}
}
public void resetForCache(SchemaContext sc) {
}
public static class TempGroupPlaceholder implements PEStorageGroup {
// true if this is an aggregation group - in that case we can't really swap the actual group for something larger
protected boolean aggregation;
// track the cost
protected int cost;
// if fulfilled by a dynamic group, index into the conn values
protected int index = -1;
public TempGroupPlaceholder(boolean agg) {
aggregation = agg;
}
public String getLoadedBy() {
return "TempGroupPlaceholder";
}
public TempGroupPlaceholder(int initialCost) {
aggregation = false;
cost = initialCost;
}
// raw plan support
public TempGroupPlaceholder(SchemaContext sc, GroupScale gs) {
index = sc.getValueManager().allocatePlaceholderGroup(sc, new PEDynamicGroup(gs));
}
protected void setBacking(SchemaContext sc, PEStorageGroup a) {
index = sc.getValueManager().allocatePlaceholderGroup(sc, a);
}
protected void createBacking(SchemaContext sc) throws PEException {
GroupScale scale = null;
if (aggregation)
scale = GroupScale.AGGREGATE;
else {
if (cost >= 0)
scale = GroupScale.SMALL;
if (cost >= 10)
scale = GroupScale.MEDIUM;
if (cost >= 100)
scale = GroupScale.LARGE;
}
index = sc.getValueManager().allocatePlaceholderGroup(sc, new PEDynamicGroup(scale));
}
@Override
public PEStorageGroup getPEStorageGroup(SchemaContext sc, ConnectionValues cv) {
return cv.getPlaceholderGroup(index);
}
@Override
public StorageGroup getPersistent(SchemaContext sc, ConnectionValues cv) {
if (index == -1)
throw new SchemaException(Pass.PLANNER, "Attempt to obtain temp group before planning complete");
return cv.getPlaceholderGroup(index).getPersistent(sc, cv);
}
@Override
public PersistentGroup persistTree(SchemaContext sc) throws PEException {
return null;
}
@Override
public StorageGroup getScheduledGroup(SchemaContext sc, ConnectionValues cv) {
return getPersistent(sc, cv);
}
@Override
public PEPersistentGroup anySite(SchemaContext sc) throws PEException {
return null;
}
@Override
public boolean comparable(SchemaContext sc, PEStorageGroup storage) {
if (storage == this) return true;
return false;
}
@Override
public boolean isSubsetOf(SchemaContext sc, PEStorageGroup storage) {
return storage == this;
}
@Override
public boolean isSingleSiteGroup() {
return aggregation;
}
@Override
public void setCost(int score) throws PEException {
if (score > cost)
cost = score;
}
public int getCost() {
return cost;
}
@Override
public boolean isTempGroup() {
return true;
}
public String toString() {
return "TempGroupPlaceholder/" + cost + (isSingleSiteGroup() ? "/agg" : "/dyn" + "/" + index);
}
}
}