com.tesora.dve.sql.schema.cache.NonMTCachedPlan.java Source code

Java tutorial

Introduction

Here is the source code for com.tesora.dve.sql.schema.cache.NonMTCachedPlan.java

Source

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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.collections.CollectionUtils;

import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.lockmanager.LockType;
import com.tesora.dve.sql.expression.TableKey;
import com.tesora.dve.sql.parser.ExtractedLiteral;
import com.tesora.dve.sql.parser.ExtractedLiteral.Type;
import com.tesora.dve.sql.schema.SchemaContext;
import com.tesora.dve.sql.statement.CacheableStatement;
import com.tesora.dve.sql.transform.execution.ConnectionValuesMap;
import com.tesora.dve.sql.transform.execution.RootExecutionPlan;
import com.tesora.dve.sql.transform.execution.RebuiltPlan;
import com.tesora.dve.sql.util.Functional;
import com.tesora.dve.sql.util.ListSet;

public class NonMTCachedPlan implements RegularCachedPlan {
    public static final String GLOBAL_CACHE_NAME = "X8U_GLOBAL_5NT";

    @SuppressWarnings("rawtypes")
    private final SchemaCacheKey[] tks;
    private final PlanCacheKey key;
    private final List<ExtractedLiteral.Type> extractedTypes;
    private final LockType lockType;
    private Map<String, SpecificCachedPlan> specificCachedPlanMap = new ConcurrentHashMap<String, NonMTCachedPlan.SpecificCachedPlan>();

    public NonMTCachedPlan(ListSet<TableKey> tabs, PlanCacheKey pck, List<ExtractedLiteral> extractedLiterals,
            LockType lt) {
        this(tabs, Functional.apply(extractedLiterals, ExtractedLiteral.typeAccessor), pck, lt);
    }

    public NonMTCachedPlan(ListSet<TableKey> tabs, List<ExtractedLiteral.Type> extractedLiterals, PlanCacheKey pck,
            LockType lt) {
        tks = buildTableKeySet(tabs);
        key = pck;
        extractedTypes = extractedLiterals;
        lockType = lt;
    }

    @Override
    public PlanCacheKey getKey() {
        return key;
    }

    @Override
    public RebuiltPlan rebuildPlan(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
        if (!isValid(sc, literals))
            return new RebuiltPlan(null, null, true, tks, lockType);

        SpecificCachedPlan nmtcp = specificCachedPlanMap.get(
                sc.getConnection().getCacheName() == null ? GLOBAL_CACHE_NAME : sc.getConnection().getCacheName());
        if (nmtcp != null) {
            return nmtcp.rebuildPlan(sc, literals);
        } else {
            // could not find the plan for the specified cache but don't clear this plan from the cache
            return new RebuiltPlan(null, null, false, tks, lockType);
        }
    }

    @Override
    public RebuiltPlan showPlan(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
        return specificCachedPlanMap.get(GLOBAL_CACHE_NAME).showPlan(sc, literals);
    }

    @Override
    public List<ExtractedLiteral.Type> getLiteralTypes() {
        return extractedTypes;
    }

    @Override
    public boolean isValid(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
        for (int i = 0; i < extractedTypes.size(); i++) {
            if (extractedTypes.get(i) != literals.get(i).getType())
                return false;
        }
        return true;
    }

    @Override
    public boolean invalidate(SchemaCacheKey<?> unloaded) {
        if (unloaded.getCacheSegment() != CacheSegment.TABLE)
            return false;
        for (int i = 0; i < tks.length; i++) {
            if (tks[i].equals(unloaded)) {
                specificCachedPlanMap.clear();
                return true;
            }
        }

        return false;
    }

    public boolean take(SchemaContext sc, CacheableStatement originalStatement, RootExecutionPlan thePlan) {
        boolean ret = true;

        if (!keysMatch(originalStatement.getAllTableKeys()) && !thePlan.isEmptyPlan()) {
            // remove this entry from the cache
            ret = false;
        } else {
            SpecificCachedPlan np = new SpecificCachedPlan(this, thePlan);
            specificCachedPlanMap.put(sc.getConnection().getCacheName() == null ? GLOBAL_CACHE_NAME
                    : sc.getConnection().getCacheName(), np);
        }
        return ret;
    }

    @SuppressWarnings("rawtypes")
    private SchemaCacheKey[] buildTableKeySet(ListSet<TableKey> tabs) {
        ArrayList<SchemaCacheKey<?>> buf = new ArrayList<SchemaCacheKey<?>>();

        for (TableKey tk : tabs) {
            SchemaCacheKey<?> sck = tk.getCacheKey();
            buf.add(sck);
        }
        return buf.toArray(new SchemaCacheKey[0]);
    }

    private boolean keysMatch(ListSet<TableKey> allTableKeys) {
        return CollectionUtils.isEqualCollection(Arrays.asList(tks), Arrays.asList(buildTableKeySet(allTableKeys)));
    }

    public static class SpecificCachedPlan implements RegularCachedPlan {

        private final NonMTCachedPlan parent;
        private final RootExecutionPlan thePlan;

        public SpecificCachedPlan(NonMTCachedPlan nmtcp, RootExecutionPlan ep) {
            parent = nmtcp;
            thePlan = ep;
            thePlan.setOwningCache(parent);
        }

        @Override
        public PlanCacheKey getKey() {
            return parent.getKey();
        }

        @Override
        public RebuiltPlan showPlan(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
            ConnectionValuesMap cvs = thePlan.resetForNewPlan(sc, literals);
            return new RebuiltPlan(thePlan, cvs, false, null, null);
        }

        @Override
        public RebuiltPlan rebuildPlan(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
            if (!isValid(sc, literals))
                return new RebuiltPlan(null, null, true, parent.tks, parent.lockType);

            if (thePlan.isEmptyPlan()) {
                return new RebuiltPlan(thePlan, null, false, parent.tks, parent.lockType);
            }

            ConnectionValuesMap cv = thePlan.resetForNewPlan(sc, literals);
            return new RebuiltPlan(thePlan, cv, false, parent.tks, parent.lockType);
        }

        @Override
        public boolean isValid(SchemaContext sc, List<ExtractedLiteral> literals) throws PEException {
            if (thePlan.getValueManager().getNumberOfLiterals() != literals.size())
                return false;
            return true;
        }

        @Override
        public boolean invalidate(SchemaCacheKey<?> unloaded) {
            return false;
        }

        @Override
        public List<Type> getLiteralTypes() {
            return null;
        }
    }
}