/** * 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.blur.command; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.blur.command.commandtype.ClusterExecuteCommand; import org.apache.blur.command.commandtype.ClusterExecuteServerReadCommand; import org.apache.blur.command.commandtype.ClusterServerReadCommand; import org.apache.blur.command.commandtype.ClusterIndexReadCommand; import org.apache.blur.command.commandtype.ServerReadCommand; import org.apache.blur.command.commandtype.IndexReadCommand; import org.apache.blur.thirdparty.thrift_0_9_0.TException; import org.apache.blur.thirdparty.thrift_0_9_0.transport.TTransportException; import org.apache.blur.thrift.BlurClient; import org.apache.blur.thrift.BlurClient.BlurClientInvocationHandler; import org.apache.blur.thrift.BlurClientManager; import org.apache.blur.thrift.ClientPool; import org.apache.blur.thrift.Connection; import org.apache.blur.thrift.generated.Arguments; import org.apache.blur.thrift.generated.Blur; import org.apache.blur.thrift.generated.Blur.Client; import org.apache.blur.thrift.generated.Blur.Iface; import org.apache.blur.thrift.generated.BlurException; import org.apache.blur.thrift.generated.ErrorType; import org.apache.blur.thrift.generated.Response; import org.apache.blur.thrift.generated.TimeoutException; import org.apache.blur.trace.Tracer; public class CommandRunner { public static Connection[] getConnection(Iface client) { if (client instanceof Proxy) { InvocationHandler invocationHandler = Proxy.getInvocationHandler(client); if (invocationHandler instanceof BlurClientInvocationHandler) { BlurClientInvocationHandler handler = (BlurClientInvocationHandler) invocationHandler; return handler.getConnections().toArray(new Connection[] {}); } } if (client == null) { throw new RuntimeException("Client cannot be null."); } throw new RuntimeException("Unknown client class [" + client.getClass() + "]"); } public static <T> Map<Shard, T> run(IndexReadCommand<T> command) throws IOException, BlurException, TException { Iface client = BlurClient.getClient(); return run(command, getConnection(client)); } public static <T> Map<Shard, T> run(IndexReadCommand<T> command, String connectionStr) throws IOException, BlurException, TException { Iface client = BlurClient.getClient(connectionStr); return run(command, getConnection(client)); } public static <T> Map<Shard, T> run(IndexReadCommand<T> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T> Map<Shard, T> run(IndexReadCommand<T> command, Connection... connection) throws IOException, BlurException, TException { return (Map<Shard, T>) runInternal((Command<?>) command, connection); } public static <T> Map<Server, T> run(ServerReadCommand<?, T> command) throws IOException, BlurException, TException { Iface client = BlurClient.getClient(); return run(command, getConnection(client)); } public static <T> Map<Server, T> run(ServerReadCommand<?, T> command, String connectionStr) throws IOException, BlurException, TException { Iface client = BlurClient.getClient(connectionStr); return run(command, getConnection(client)); } public static <T> Map<Server, T> run(ServerReadCommand<?, T> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T> Map<Server, T> run(ServerReadCommand<?, T> command, Connection... connection) throws IOException, BlurException, TException { return (Map<Server, T>) runInternal((Command<?>) command, connection); } public static <T1, T2> T2 run(ClusterIndexReadCommand<T1, T2> command) throws IOException, BlurException, TException { return run(command, getConnection(BlurClient.getClient())); } @SuppressWarnings("unchecked") public static <T1, T2> T2 run(ClusterIndexReadCommand<T1, T2> command, String connectioStr) throws IOException, BlurException, TException { return (T2) runInternal((Command<?>) command, getConnection(BlurClient.getClient(connectioStr))); } public static <T1, T2> T2 run(ClusterIndexReadCommand<T1, T2> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T1, T2> T2 run(ClusterIndexReadCommand<T1, T2> command, Connection... connection) throws IOException, BlurException, TException { return (T2) runInternal((Command<?>) command, connection); } public static <T> T run(ClusterServerReadCommand<T> command) throws IOException, BlurException, TException { return run(command, getConnection(BlurClient.getClient())); } @SuppressWarnings("unchecked") public static <T> T run(ClusterServerReadCommand<T> command, String connectioStr) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, getConnection(BlurClient.getClient(connectioStr))); } public static <T> T run(ClusterServerReadCommand<T> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T> T run(ClusterServerReadCommand<T> command, Connection... connection) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, connection); } public static <T> T run(ClusterExecuteCommand<T> command) throws IOException, BlurException, TException { return run(command, getConnection(BlurClient.getClient())); } @SuppressWarnings("unchecked") public static <T> T run(ClusterExecuteCommand<T> command, String connectioStr) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, getConnection(BlurClient.getClient(connectioStr))); } public static <T> T run(ClusterExecuteCommand<T> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T> T run(ClusterExecuteCommand<T> command, Connection... connection) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, connection); } public static <T> T run(ClusterExecuteServerReadCommand<T> command) throws IOException, BlurException, TException { return run(command, getConnection(BlurClient.getClient())); } @SuppressWarnings("unchecked") public static <T> T run(ClusterExecuteServerReadCommand<T> command, String connectioStr) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, getConnection(BlurClient.getClient(connectioStr))); } public static <T> T run(ClusterExecuteServerReadCommand<T> command, Blur.Iface client) throws IOException, BlurException, TException { return run(command, getConnection(client)); } @SuppressWarnings("unchecked") public static <T> T run(ClusterExecuteServerReadCommand<T> command, Connection... connection) throws IOException, BlurException, TException { return (T) runInternal((Command<?>) command, connection); } public static Object runInternal(Command<?> command, Connection... connectionsArray) throws TTransportException, IOException, BlurException, TimeoutException, TException { BlurObjectSerDe serde = new BlurObjectSerDe(); Arguments arguments = CommandUtil.toArguments(command, serde); Object thriftObject = runInternalReturnThriftObject(command.getName(), arguments, connectionsArray); return serde.fromSupportedThriftObject(thriftObject); } public static Object runInternalReturnThriftObject(String name, Arguments arguments, Connection... connectionsArray) throws TTransportException, IOException, BlurException, TimeoutException, TException { List<Connection> connections = new ArrayList<Connection>(Arrays.asList(connectionsArray)); Collections.shuffle(connections); for (Connection connection : connections) { if (BlurClientManager.isBadConnection(connection)) { continue; } ClientPool clientPool = BlurClientManager.getClientPool(); Client client = clientPool.getClient(connection); try { Long executionId = null; Response response; INNER: while (true) { Tracer tracer = BlurClientManager.setupClientPreCall(client); try { if (executionId == null) { response = client.execute(name, arguments); } else { response = client.reconnect(executionId); } break INNER; } catch (TimeoutException te) { executionId = te.getInstanceExecutionId(); } finally { if (tracer != null) { tracer.done(); } } } return CommandUtil.fromThriftResponseToObject(response); } finally { clientPool.returnClient(connection, client); } } throw new BlurException("All connections bad. [" + connections + "]", null, ErrorType.UNKNOWN); } }