Package com.facebook.presto.sql.planner

Source Code of com.facebook.presto.sql.planner.DistributedExecutionPlanner$NodeSplits

/*
* Licensed 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 com.facebook.presto.sql.planner;

import com.facebook.presto.execution.SampledSplitSource;
import com.facebook.presto.metadata.ShardManager;
import com.facebook.presto.spi.Partition;
import com.facebook.presto.spi.PartitionResult;
import com.facebook.presto.spi.SplitSource;
import com.facebook.presto.spi.TupleDomain;
import com.facebook.presto.split.SplitManager;
import com.facebook.presto.sql.planner.plan.AggregationNode;
import com.facebook.presto.sql.planner.plan.ExchangeNode;
import com.facebook.presto.sql.planner.plan.FilterNode;
import com.facebook.presto.sql.planner.plan.JoinNode;
import com.facebook.presto.sql.planner.plan.LimitNode;
import com.facebook.presto.sql.planner.plan.MarkDistinctNode;
import com.facebook.presto.sql.planner.plan.MaterializedViewWriterNode;
import com.facebook.presto.sql.planner.plan.OutputNode;
import com.facebook.presto.sql.planner.plan.PlanNode;
import com.facebook.presto.sql.planner.plan.PlanNodeId;
import com.facebook.presto.sql.planner.plan.PlanVisitor;
import com.facebook.presto.sql.planner.plan.ProjectNode;
import com.facebook.presto.sql.planner.plan.SampleNode;
import com.facebook.presto.sql.planner.plan.SemiJoinNode;
import com.facebook.presto.sql.planner.plan.SinkNode;
import com.facebook.presto.sql.planner.plan.SortNode;
import com.facebook.presto.sql.planner.plan.TableCommitNode;
import com.facebook.presto.sql.planner.plan.TableScanNode;
import com.facebook.presto.sql.planner.plan.TableWriterNode;
import com.facebook.presto.sql.planner.plan.TopNNode;
import com.facebook.presto.sql.planner.plan.WindowNode;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import javax.inject.Inject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

public class DistributedExecutionPlanner
{
    private final SplitManager splitManager;
    private final ShardManager shardManager;

    @Inject
    public DistributedExecutionPlanner(SplitManager splitManager, ShardManager shardManager)
    {
        this.splitManager = checkNotNull(splitManager, "splitManager is null");
        this.shardManager = checkNotNull(shardManager, "databaseShardManager is null");
    }

    public StageExecutionPlan plan(SubPlan root)
    {
        return plan(root, Predicates.<Partition>alwaysTrue());
    }

    public StageExecutionPlan plan(SubPlan root, Predicate<Partition> materializedViewPartitionPredicate)
    {
        PlanFragment currentFragment = root.getFragment();

        // get splits for this fragment, this is lazy so split assignments aren't actually calculated here
        Visitor visitor = new Visitor();
        NodeSplits nodeSplits = currentFragment.getRoot().accept(visitor, materializedViewPartitionPredicate);

        // create child stages
        ImmutableList.Builder<StageExecutionPlan> dependencies = ImmutableList.builder();
        for (SubPlan childPlan : root.getChildren()) {
            dependencies.add(plan(childPlan, materializedViewPartitionPredicate));
        }

        return new StageExecutionPlan(currentFragment,
                nodeSplits.getDataSource(),
                dependencies.build(),
                visitor.getOutputReceivers());
    }

    private final class Visitor
            extends PlanVisitor<Predicate<Partition>, NodeSplits>
    {
        private final Map<PlanNodeId, OutputReceiver> outputReceivers = new HashMap<>();

        public Map<PlanNodeId, OutputReceiver> getOutputReceivers()
        {
            return ImmutableMap.copyOf(outputReceivers);
        }

        @Override
        public NodeSplits visitTableScan(TableScanNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            List<Partition> partitions = FluentIterable.from(getPartitions(node))
                    .filter(materializedViewPartitionPredicate)
                    .toList();

            // get dataSource for table
            SplitSource splitSource = splitManager.getPartitionSplits(node.getTable(), partitions);

            return new NodeSplits(node.getId(), splitSource);
        }

        private List<Partition> getPartitions(TableScanNode node)
        {
            if (node.getGeneratedPartitions().isPresent()) {
                return node.getGeneratedPartitions().get().getPartitions();
            }

            PartitionResult allPartitions = splitManager.getPartitions(node.getTable(), Optional.<TupleDomain>absent());
            return allPartitions.getPartitions();
        }

        @Override
        public NodeSplits visitJoin(JoinNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            NodeSplits leftSplits = node.getLeft().accept(this, materializedViewPartitionPredicate);
            NodeSplits rightSplits = node.getRight().accept(this, materializedViewPartitionPredicate);
            if (leftSplits.getDataSource().isPresent() && rightSplits.getDataSource().isPresent()) {
                throw new IllegalArgumentException("Both left and right join nodes are partitioned"); // TODO: "partitioned" may not be the right term
            }
            return leftSplits.getDataSource().isPresent() ? leftSplits : rightSplits;
        }

        @Override
        public NodeSplits visitSemiJoin(SemiJoinNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            NodeSplits sourceSplits = node.getSource().accept(this, materializedViewPartitionPredicate);
            NodeSplits filteringSourceSplits = node.getFilteringSource().accept(this, materializedViewPartitionPredicate);
            if (sourceSplits.getDataSource().isPresent() && filteringSourceSplits.getDataSource().isPresent()) {
                throw new IllegalArgumentException("Both source and filteringSource semi join nodes are partitioned"); // TODO: "partitioned" may not be the right term
            }
            return sourceSplits.getDataSource().isPresent() ? sourceSplits : filteringSourceSplits;
        }

        @Override
        public NodeSplits visitExchange(ExchangeNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            // exchange node does not have splits
            return new NodeSplits(node.getId());
        }

        @Override
        public NodeSplits visitFilter(FilterNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitSample(SampleNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            switch(node.getSampleType()) {
                case BERNOULLI:
                    return node.getSource().accept(this, materializedViewPartitionPredicate);

                case SYSTEM: {
                    NodeSplits nodeSplits = node.getSource().accept(this, materializedViewPartitionPredicate);
                    if (nodeSplits.getDataSource().isPresent()) {
                        SplitSource sampledSplitSource = new SampledSplitSource(nodeSplits.getDataSource().get(), node.getSampleRatio());
                        return new NodeSplits(node.getId(), sampledSplitSource);
                    }
                    else {
                        // table sampling on a sub query without splits is meaningless
                        return nodeSplits;
                    }
                }
                default:
                    throw new UnsupportedOperationException("Sampling is not supported for type " + node.getSampleType());
            }
        }

        @Override
        public NodeSplits visitAggregation(AggregationNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitMarkDistinct(MarkDistinctNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitWindow(WindowNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitProject(ProjectNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitTopN(TopNNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitOutput(OutputNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitLimit(LimitNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitSort(SortNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitSink(SinkNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitTableWriter(TableWriterNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitTableCommit(TableCommitNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            return node.getSource().accept(this, materializedViewPartitionPredicate);
        }

        @Override
        public NodeSplits visitMaterializedViewWriter(MaterializedViewWriterNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            MaterializedViewWriter materializedViewWriter = new MaterializedViewWriter(node, shardManager);

            // get source splits
            NodeSplits nodeSplits = node.getSource().accept(this, materializedViewWriter.getPartitionPredicate());
            checkState(nodeSplits.getDataSource().isPresent(), "No splits present for import");
            SplitSource splitSource = nodeSplits.getDataSource().get();

            // record output
            outputReceivers.put(node.getId(), materializedViewWriter.getOutputReceiver());

            // wrap splits with table writer info
            return new NodeSplits(node.getId(), materializedViewWriter.wrapSplitSource(nodeSplits.getPlanNodeId(), splitSource));
        }

        @Override
        protected NodeSplits visitPlan(PlanNode node, Predicate<Partition> materializedViewPartitionPredicate)
        {
            throw new UnsupportedOperationException("not yet implemented: " + node.getClass().getName());
        }
    }

    private class NodeSplits
    {
        private final PlanNodeId planNodeId;
        private final Optional<SplitSource> dataSource;

        private NodeSplits(PlanNodeId planNodeId)
        {
            this.planNodeId = planNodeId;
            this.dataSource = Optional.absent();
        }

        private NodeSplits(PlanNodeId planNodeId, SplitSource splitSource)
        {
            this.planNodeId = planNodeId;
            this.dataSource = Optional.of(splitSource);
        }

        public PlanNodeId getPlanNodeId()
        {
            return planNodeId;
        }

        public Optional<SplitSource> getDataSource()
        {
            return dataSource;
        }
    }
}
TOP

Related Classes of com.facebook.presto.sql.planner.DistributedExecutionPlanner$NodeSplits

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.