All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.table.plan.optimize.FlinkChainedPrograms.scala Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.flink.table.plan.optimize

import org.apache.flink.table.util.Logging

import org.apache.calcite.rel.RelNode

import java.util

import scala.collection.JavaConverters._
import scala.collection.mutable

/**
  * FlinkChainedPrograms contains a sequence of [[FlinkOptimizeProgram]]s which are chained
  * together.
  *
  * The chained-order of programs can be adjusted by addXXX and [[remove]] methods.
  *
  * When [[optimize]] method called, each program's optimize method will be called in sequence.
  *
  * @tparam OC OptimizeContext
  */
class FlinkChainedPrograms[OC <: OptimizeContext] extends Logging {
  private val programMap = new mutable.HashMap[String, FlinkOptimizeProgram[OC]]()
  private val programNames = new mutable.ListBuffer[String]()

  /**
    * Calling each program's optimize method in sequence.
    */
  def optimize(root: RelNode, context: OC): RelNode = {
    programNames.foldLeft(root) {
      (input, name) =>
        val start = System.currentTimeMillis()
        val result = get(name)
            .getOrElse(throw new RuntimeException(s"program of $name does not exist"))
            .optimize(input, context)
        val end = System.currentTimeMillis()
        LOG.info("optimize " + name + " cost " + (end - start) + " ms.")
        result
    }
  }

  /**
    * Gets program associated with the given name. If not found, return [[None]].
    */
  def get(name: String): Option[FlinkOptimizeProgram[OC]] = {
    val program = programMap.get(name)
    if (program.isDefined) {
      // using Option instead of Some to convert null to None
      Option(programMap(name))
    } else {
      None
    }
  }

  /**
    * Gets FlinkRuleSetProgram associated with the given name. If the program is not found or is
    * not a [[FlinkRuleSetProgram]], return [[None]].
    */
  def getFlinkRuleSetProgram(name: String): Option[FlinkRuleSetProgram[OC]] = {
    get(name).getOrElse(None) match {
      case p: FlinkRuleSetProgram[OC] => Some(p)
      case _ => None
    }
  }

  /**
    * Appends the specified program to the end of program collection.
    *
    * @return false if program collection contains the specified program; otherwise true.
    */
  def addLast(name: String, program: FlinkOptimizeProgram[OC]): Boolean = {
    if (programNames.contains(name)) {
      false
    } else {
      programNames += name
      programMap.put(name, program)
      true
    }
  }

  /**
    * Inserts the specified program to the beginning of program collection.
    *
    * @return false if program collection contains the specified program; otherwise true.
    */
  def addFirst(name: String, program: FlinkOptimizeProgram[OC]): Boolean = {
    if (programNames.contains(name)) {
      false
    } else {
      programNames.insert(0, name)
      programMap.put(name, program)
      true
    }
  }

  /**
    * Inserts the specified program before `nameOfBefore`.
    *
    * @return false if program collection contains the specified program or
    *         does not contain `nameOfBefore`; otherwise true.
    */
  def addBefore(nameOfBefore: String, name: String, program: FlinkOptimizeProgram[OC]): Boolean = {
    if (programNames.contains(name) || !programNames.contains(nameOfBefore)) {
      false
    } else if (programNames.isEmpty) {
      addLast(name, program)
    } else {
      val index = programNames.indexOf(nameOfBefore)
      programNames.insert(index, name)
      programMap.put(name, program)
      true
    }
  }

  /**
    * Removes program associated with the given name from program collection.
    *
    * @return The removed program associated with the given name. If not found, return [[None]].
    */
  def remove(name: String): Option[FlinkOptimizeProgram[OC]] = {
    val index = programNames.indexOf(name)
    if (index >= 0) {
      programNames.remove(index)
    }
    programMap.remove(name)
  }

  /**
    * Returns program names with chained order.
    */
  def getProgramNames: util.List[String] = new util.ArrayList[String](programNames.asJava)

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy