/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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/>. */ package com.foundationdb.sql.optimizer.rule; import com.foundationdb.sql.optimizer.plan.PlanNode; import org.slf4j.Logger; import java.util.List; import java.util.Properties; /** The context / owner of a {@link PlanContext}, shared among several of them. */ public class RulesContext { // TODO: Need more much sophisticated invocation mechanism. private Properties properties; private List<? extends BaseRule> rules; protected RulesContext() { } protected void initProperties(Properties properties) { this.properties = properties; } protected void initRules(List<? extends BaseRule> rules) { this.rules = rules; } protected void initDone() { assert (properties != null) : "initProperties() not called"; assert (rules != null) : "initRules() not called"; } protected boolean rulesAre(List<? extends BaseRule> expected) { return rules == expected; } /** Make context with these rules. Just for testing. */ public static RulesContext create(List<? extends BaseRule> rules, Properties properties) { RulesContext context = new RulesContext(); context.initProperties(properties); context.initRules(rules); context.initDone(); return context; } public void applyRules(PlanContext plan) { boolean logged = false; for (BaseRule rule : rules) { Logger logger = rule.getLogger(); boolean debug = logger.isDebugEnabled(); if (debug && !logged) { logger.debug("Before {}:\n{}", rule.getName(), plan.planString(PlanNode.SummaryConfiguration.DEFAULT)); } beginRule(rule); try { rule.apply(plan); } catch (RuntimeException e) { if (debug) { String msg = "error while applying " + rule.getName() + " to " + plan.planString(PlanNode.SummaryConfiguration.DEFAULT); logger.debug(msg, e); } throw e; } finally { endRule(rule); } if (debug) { logger.debug("After {}:\n{}", rule.getName(), plan.planString(PlanNode.SummaryConfiguration.DEFAULT)); } logged = debug; } } /** Extend this to implement tracing, etc. */ public void beginRule(BaseRule rule) { } public void endRule(BaseRule rule) { } /** Get optimizer configuration. */ public Properties getProperties() { return properties; } public String getProperty(String key) { return properties.getProperty(key); } public String getProperty(String key, String defval) { return properties.getProperty(key, defval); } }