/* * 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.flume.api; import org.apache.flume.Event; import org.apache.flume.FlumeException; import org.apache.flume.event.EventBuilder; import org.apache.flume.thrift.Status; import org.apache.flume.thrift.ThriftFlumeEvent; import org.apache.flume.thrift.ThriftSourceProtocol; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.THsHaServer; import org.apache.thrift.server.TServer; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TFastFramedTransport; import org.apache.thrift.transport.TServerTransport; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; public class ThriftTestingSource { public final Queue<Event> flumeEvents = new ConcurrentLinkedQueue<Event>(); private final TServer server; public int batchCount = 0; public int individualCount = 0; public int incompleteBatches = 0; private AtomicLong delay = null; public void setDelay(AtomicLong delay) { this.delay = delay; } private class ThriftOKHandler implements ThriftSourceProtocol.Iface { public ThriftOKHandler() { } @Override public Status append(ThriftFlumeEvent event) throws TException { flumeEvents.add(EventBuilder.withBody(event.getBody(), event.getHeaders())); individualCount++; return Status.OK; } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { batchCount++; if (events.size() < 10) { incompleteBatches++; } for (ThriftFlumeEvent event : events) { flumeEvents.add(EventBuilder.withBody(event.getBody(), event.getHeaders())); } return Status.OK; } } private class ThriftFailHandler implements ThriftSourceProtocol.Iface { @Override public Status append(ThriftFlumeEvent event) throws TException { return Status.FAILED; } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { return Status.FAILED; } } private class ThriftErrorHandler implements ThriftSourceProtocol.Iface { @Override public Status append(ThriftFlumeEvent event) throws TException { throw new FlumeException("Forced Error"); } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { throw new FlumeException("Forced Error"); } } private class ThriftSlowHandler extends ThriftOKHandler { @Override public Status append(ThriftFlumeEvent event) throws TException { try { TimeUnit.MILLISECONDS.sleep(1550); } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.append(event); } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { try { TimeUnit.MILLISECONDS.sleep(1550); } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.appendBatch(events); } } private class ThriftTimeoutHandler extends ThriftOKHandler { @Override public Status append(ThriftFlumeEvent event) throws TException { try { TimeUnit.MILLISECONDS.sleep(5000); } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.append(event); } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { try { TimeUnit.MILLISECONDS.sleep(5000); } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.appendBatch(events); } } private class ThriftAlternateHandler extends ThriftOKHandler { @Override public Status append(ThriftFlumeEvent event) throws TException { try { if (delay != null) { TimeUnit.MILLISECONDS.sleep(delay.get()); } } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.append(event); } @Override public Status appendBatch(List<ThriftFlumeEvent> events) throws TException { try { if (delay != null) { TimeUnit.MILLISECONDS.sleep(delay.get()); } } catch (InterruptedException e) { throw new FlumeException("Error", e); } return super.appendBatch(events); } } private ThriftSourceProtocol.Iface getHandler(String handlerName) { ThriftSourceProtocol.Iface handler = null; if (handlerName.equals(HandlerType.OK.name())) { handler = new ThriftOKHandler(); } else if (handlerName.equals(HandlerType.FAIL.name())) { handler = new ThriftFailHandler(); } else if (handlerName.equals(HandlerType.ERROR.name())) { handler = new ThriftErrorHandler(); } else if (handlerName.equals(HandlerType.SLOW.name())) { handler = new ThriftSlowHandler(); } else if (handlerName.equals(HandlerType.TIMEOUT.name())) { handler = new ThriftTimeoutHandler(); } else if (handlerName.equals(HandlerType.ALTERNATE.name())) { handler = new ThriftAlternateHandler(); } return handler; } public ThriftTestingSource(String handlerName, int port, String protocol) throws Exception { TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(new InetSocketAddress("0.0.0.0", port)); ThriftSourceProtocol.Iface handler = getHandler(handlerName); TProtocolFactory transportProtocolFactory = null; if (protocol != null && protocol == ThriftRpcClient.BINARY_PROTOCOL) { transportProtocolFactory = new TBinaryProtocol.Factory(); } else { transportProtocolFactory = new TCompactProtocol.Factory(); } server = new THsHaServer(new THsHaServer.Args(serverTransport).processor( new ThriftSourceProtocol.Processor(handler)).protocolFactory( transportProtocolFactory)); Executors.newSingleThreadExecutor().submit(new Runnable() { @Override public void run() { server.serve(); } }); } public ThriftTestingSource(String handlerName, int port, String protocol, String keystore, String keystorePassword, String keyManagerType, String keystoreType) throws Exception { TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(); params.setKeyStore(keystore, keystorePassword, keyManagerType, keystoreType); TServerSocket serverTransport = TSSLTransportFactory.getServerSocket( port, 10000, InetAddress.getByName("0.0.0.0"), params); ThriftSourceProtocol.Iface handler = getHandler(handlerName); Class serverClass = Class.forName("org.apache.thrift" + ".server.TThreadPoolServer"); Class argsClass = Class.forName("org.apache.thrift.server" + ".TThreadPoolServer$Args"); TServer.AbstractServerArgs args = (TServer.AbstractServerArgs) argsClass .getConstructor(TServerTransport.class) .newInstance(serverTransport); Method m = argsClass.getDeclaredMethod("maxWorkerThreads", int.class); m.invoke(args, Integer.MAX_VALUE); TProtocolFactory transportProtocolFactory = null; if (protocol != null && protocol == ThriftRpcClient.BINARY_PROTOCOL) { transportProtocolFactory = new TBinaryProtocol.Factory(); } else { transportProtocolFactory = new TCompactProtocol.Factory(); } args.protocolFactory(transportProtocolFactory); args.inputTransportFactory(new TFastFramedTransport.Factory()); args.outputTransportFactory(new TFastFramedTransport.Factory()); args.processor(new ThriftSourceProtocol.Processor<ThriftSourceProtocol.Iface>(handler)); server = (TServer) serverClass.getConstructor(argsClass).newInstance(args); Executors.newSingleThreadExecutor().submit(new Runnable() { @Override public void run() { server.serve(); } }); } public enum HandlerType { OK, FAIL, ERROR, SLOW, TIMEOUT, ALTERNATE; } public void stop() { server.stop(); } }