Package io.crate.executor.transport.merge

Source Code of io.crate.executor.transport.merge.TransportMergeNodeAction

/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements.  See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.  Crate 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/

package io.crate.executor.transport.merge;

import io.crate.Streamer;
import io.crate.executor.transport.DistributedResultRequestHandler;
import io.crate.executor.transport.TransportActionProvider;
import io.crate.executor.transport.distributed.DistributedRequestContextManager;
import io.crate.executor.transport.distributed.DistributedResultRequest;
import io.crate.executor.transport.distributed.DistributedResultResponse;
import io.crate.metadata.Functions;
import io.crate.metadata.ReferenceResolver;
import io.crate.operation.DownstreamOperation;
import io.crate.operation.DownstreamOperationFactory;
import io.crate.operation.ImplementationSymbolVisitor;
import io.crate.operation.collect.StatsTables;
import io.crate.operation.merge.MergeOperation;
import io.crate.planner.RowGranularity;
import io.crate.planner.node.PlanNodeStreamerVisitor;
import io.crate.planner.node.dql.MergeNode;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.*;

import java.io.IOException;


public class TransportMergeNodeAction {

    private final ESLogger logger = Loggers.getLogger(getClass());
    private final DistributedRequestContextManager contextManager;

    public final static String mergeRowsAction = "crate/sql/node/merge/add_rows";
    public final static String failAction = "crate/sql/node/merge/fail";
    private final static String startMergeAction = "crate/sql/node/merge/start";
    private final TransportService transportService;
    private final ClusterService clusterService;
    private final PlanNodeStreamerVisitor planNodeStreamerVisitor;
    private final ThreadPool threadPool;

    @Inject
    public TransportMergeNodeAction(final ClusterService clusterService,
                                    final Settings settings,
                                    final TransportActionProvider transportActionProvider,
                                    TransportService transportService,
                                    ReferenceResolver referenceResolver,
                                    Functions functions,
                                    final ThreadPool threadPool,
                                    StatsTables statsTables) {
        this.transportService = transportService;
        this.clusterService = clusterService;
        this.threadPool = threadPool;

        final ImplementationSymbolVisitor implementationSymbolVisitor = new ImplementationSymbolVisitor(
                referenceResolver, functions, RowGranularity.DOC
        );

        planNodeStreamerVisitor = new PlanNodeStreamerVisitor(functions);
        this.contextManager = new DistributedRequestContextManager(new DownstreamOperationFactory<MergeNode>() {
            @Override
            public DownstreamOperation create(MergeNode node) {
                return new MergeOperation(
                        clusterService,
                        settings,
                        transportActionProvider,
                        implementationSymbolVisitor,
                        node
                );
            }
        }, functions, statsTables);

        transportService.registerHandler(startMergeAction, new StartMergeHandler());
        transportService.registerHandler(failAction, new FailureHandler(contextManager));
        transportService.registerHandler(mergeRowsAction, new DistributedResultRequestHandler(contextManager));
    }

    public void startMerge(String node, NodeMergeRequest request, ActionListener<NodeMergeResponse> listener) {
        logger.trace("startMerge: {}", node);
        new AsyncMergeStartAction(node, request, listener).start();
    }

    public void mergeRows(String node, DistributedResultRequest request, ActionListener<DistributedResultResponse> listener) {
        new AsyncMergeRowsAction(node, request, listener).start();
    }

    protected String executorName() {
        return ThreadPool.Names.SEARCH;
    }

    private class AsyncMergeRowsAction {

        private final DiscoveryNode node;
        private final DistributedResultRequest request;
        private final ActionListener<DistributedResultResponse> listener;

        public AsyncMergeRowsAction(String node, DistributedResultRequest request, ActionListener<DistributedResultResponse> listener) {
            this.node = clusterService.state().nodes().get(node);
            this.request = request;
            this.listener = listener;
        }

        public void start() {
            transportService.sendRequest(
                    node,
                    mergeRowsAction,
                    request,
                    new BaseTransportResponseHandler<DistributedResultResponse>() {
                        @Override
                        public DistributedResultResponse newInstance() {
                            return new DistributedResultResponse();
                        }

                        @Override
                        public void handleResponse(DistributedResultResponse response) {
                            listener.onResponse(response);
                        }

                        @Override
                        public void handleException(TransportException exp) {
                            listener.onFailure(exp);
                        }

                        @Override
                        public String executor() {
                            return executorName();
                        }
                    }
            );
        }
    }

    private class AsyncMergeStartAction {

        private final DiscoveryNode node;
        private final NodeMergeRequest request;
        private final ActionListener<NodeMergeResponse> listener;
        private final Streamer<?>[] streamers;
        private final String nodeId;

        public AsyncMergeStartAction(String node, NodeMergeRequest request, ActionListener<NodeMergeResponse> listener) {
            this.node = clusterService.state().nodes().get(node);
            this.nodeId = this.node.id();
            this.request = request;
            this.listener = listener;
            this.streamers = planNodeStreamerVisitor.process(request.mergeNode()).outputStreamers();
        }

        public void start() {
            if (nodeId.equals("_local") || nodeId.equals(clusterService.state().nodes().localNode().getId())) {
                logger.trace("AsyncMergeStartAction.start local node: {} {}", this, nodeId);
                threadPool.executor(executorName()).execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            contextManager.createContext(request.mergeNode(), new ActionListener<NodeMergeResponse>() {
                                @Override
                                public void onResponse(NodeMergeResponse nodeMergeResponse) {
                                    logger.trace("createContext.onRespnose", nodeId);
                                    listener.onResponse(nodeMergeResponse);
                                }

                                @Override
                                public void onFailure(Throwable e) {
                                    logger.trace("createContext.onFailure", nodeId);
                                    listener.onFailure(e);
                                }
                            });
                        } catch (IOException e) {
                            logger.error("createContext.catched local exception node: {}", nodeId, e);
                            listener.onFailure(e);
                        }
                    }
                });
            } else {
                logger.trace("AsyncMergeStartAction.start remote node: {} {}", this, nodeId);
                transportService.sendRequest(
                        node,
                        startMergeAction,
                        request,
                        new BaseTransportResponseHandler<NodeMergeResponse>() {
                            @Override
                            public NodeMergeResponse newInstance() {
                                return new NodeMergeResponse(streamers);
                            }

                            @Override
                            public void handleResponse(NodeMergeResponse response) {
                                logger.trace("NodeMergeResponse.handleResponse: {}", nodeId);
                                listener.onResponse(response);
                            }

                            @Override
                            public void handleException(TransportException exp) {
                                logger.error("NodeMergeResponse.handleException {}", exp);
                                listener.onFailure(exp);
                            }

                            @Override
                            public String executor() {
                                return executorName();
                            }
                        }
                );
            }
        }
    }

    private class StartMergeHandler extends BaseTransportRequestHandler<NodeMergeRequest> {

        @Override
        public NodeMergeRequest newInstance() {
            return new NodeMergeRequest();
        }

        @Override
        public void messageReceived(final NodeMergeRequest request, final TransportChannel channel) throws Exception {
            contextManager.createContext(request.mergeNode(), new ActionListener<NodeMergeResponse>() {
                @Override
                public void onResponse(NodeMergeResponse nodeMergeResponse) {
                    try {
                        channel.sendResponse(nodeMergeResponse);
                    } catch (IOException e) {
                        onFailure(e);
                    }
                }

                @Override
                public void onFailure(Throwable e) {
                    try {
                        channel.sendResponse(e);
                    } catch (IOException e1) {
                        logger.error(e.getMessage(), e);
                    }
                }
            });
        }

        @Override
        public String executor() {
            return ThreadPool.Names.GENERIC;
        }
    }
}
TOP

Related Classes of io.crate.executor.transport.merge.TransportMergeNodeAction

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.