package com.tesora.dve.sql.schema.cache;
/*
* #%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.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.cache.CacheStats;
import com.tesora.dve.common.PEConstants;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.util.Functional;
public class MutableSchemaSource extends BasicSchemaSource implements SchemaSource {
private final PlanCache planCache;
private final PreparedStatementPlanCache pstmtCache;
private final long versionAtCreation;
private final boolean mutable;
public MutableSchemaSource(long version, boolean mutable, PreparedStatementPlanCache pcache) {
super(mutable ? CacheType.MUTABLE : CacheType.UNMUTABLE);
versionAtCreation = version;
this.mutable = mutable;
this.pstmtCache = pcache;
this.planCache = new MutablePlanCache();
}
@Override
public long getVersion() {
return versionAtCreation;
}
@Override
public CacheType getType() {
return (mutable ? CacheType.MUTABLE : CacheType.UNMUTABLE);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public <T> SchemaEdge<T> buildEdge(T p) {
Cacheable c = (Cacheable)p;
SchemaEdge<T> e = (p == null ? new LoadedEdge() : new LoadedEdge(c.getCacheKey()));
if (p != null) {
tloaded.put(e.getCacheKey(),p);
}
return e;
}
@Override
public <T> SchemaEdge<T> buildTransientEdge(T p) {
return new TransientEdge<T>(p);
}
@Override
public <T> SchemaEdge<T> buildEdgeFromKey(SchemaCacheKey<T> sck) {
return new LoadedEdge<T>(sck);
}
@Override
public boolean isPlanCacheEmpty() {
if (mutable) return true;
return planCache.isEmpty();
}
@Override
public boolean canCachePlans(SchemaContext sc) {
if (mutable) return false;
return (SchemaSourceFactory.getCacheLimits(sc).getLimit(CacheSegment.PLAN) > 0);
}
@Override
public void putCachedPlan(RegularCachedPlan cp) {
planCache.put(cp);
}
@Override
public RegularCachedPlan getCachedPlan(SchemaContext sc, PlanCacheKey pck) {
return planCache.get(sc,pck);
}
@Override
public void clearCachedPlan(RegularCachedPlan pck) {
planCache.invalidate(pck.getKey());
}
@Override
public void onCacheLimitUpdate(CacheSegment cs, CacheLimits limits) {
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("MutableSchemaSource@").append(System.identityHashCode(this))
.append(", init version ").append(versionAtCreation).append(", mutable=").append(mutable).append(PEConstants.LINE_SEPARATOR);
buf.append("by SchemaCacheKey {")
.append(Functional.joinToString(tloaded.keySet(), ", ")).append("}");
return buf.toString();
}
@Override
public CachedPreparedStatement getPreparedStatement(PlanCacheKey pck) {
return pstmtCache.getPreparedStatement(pck);
}
@Override
public CachedPreparedStatement getPreparedStatement(SchemaContext sc, int connID, String stmtID) throws PEException {
return pstmtCache.getPreparedStatement(sc,connID,stmtID);
}
@Override
public void putPreparedStatement(CachedPreparedStatement cps, int connID, String stmtID, String rawSQL, boolean reregister) throws PEException {
pstmtCache.putPreparedStatement(cps, connID, stmtID, rawSQL, reregister);
}
@Override
public void clearPreparedStatement(int connID, String stmtID) {
pstmtCache.clearPreparedStatement(connID, stmtID);
}
@Override
public void invalidate(SchemaCacheKey<?> sck) {
pstmtCache.invalidate(sck);
}
private static class MutablePlanCache extends PlanCache {
private final ConcurrentHashMap<PlanCacheKey, RegularCachedPlan> planCache = new ConcurrentHashMap<PlanCacheKey, RegularCachedPlan>();
// in the mutable cache there is no limit to the size of the raw plan cache
public MutablePlanCache() {
super(-1);
}
@Override
public boolean isMainEmpty() {
return planCache.isEmpty();
}
@Override
public long getMainSize() {
return planCache.size();
}
@Override
public CacheStats getMainStats() {
return null;
}
@Override
public void resetMainStats() {
}
@Override
public void invalidateMain(PlanCacheKey pck) {
planCache.remove(pck);
}
@Override
public RegularCachedPlan getMain(PlanCacheKey pck) {
return planCache.get(pck);
}
@Override
public void putMain(RegularCachedPlan rcp) {
planCache.put(rcp.getKey(),rcp);
}
@Override
public Map<PlanCacheKey, RegularCachedPlan> getMainMap() {
return planCache;
}
}
}