<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/executor/CustomThreadFactory.java<|end_filename|>
package com.didiglobal.pressir.thrift.executor;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName CustomThreadFactory
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-02 14:54
 */
public class CustomThreadFactory implements ThreadFactory {
    private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);

    private final String poolName;
    private final ThreadGroup threadGroup;
    private final String threadNamePrefix;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private int threadPriority;

    public CustomThreadFactory(String poolName) {
        this(poolName, Thread.NORM_PRIORITY);
    }

    CustomThreadFactory(String poolName, int threadPriority) {
        SecurityManager securityManager = System.getSecurityManager();
        this.poolName = poolName;
        this.threadGroup = (securityManager != null) ?
                securityManager.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        this.threadPriority = threadPriority;
        this.threadNamePrefix = poolName + '-' + POOL_NUMBER.getAndIncrement() + '-';
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(
                this.threadGroup,
                r,
                this.threadNamePrefix + this.threadNumber.getAndIncrement(),
                0);
        if (t.isDaemon()) {
            t.setDaemon(false);
        }
        if (t.getPriority() != this.threadPriority) {
            t.setPriority(this.threadPriority);
        }
        return t;
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/monitor/Statistic.java<|end_filename|>
package com.didiglobal.pressir.thrift.monitor;


import com.didiglobal.pressir.thrift.console.ConsolePrinter;
import com.didiglobal.pressir.thrift.constant.Constants;
import org.apache.logging.log4j.util.Strings;
import org.apache.thrift.TApplicationException;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName Statistic
 * @Description 统计结果
 * @Author pressir
 * @Date 2019-08-28 10:43
 */
class Statistic {
    private static final Logger LOGGER = LoggerFactory.getLogger(Statistic.class);

    private static final Map<Integer, String> TRANSPORT_EXCEPTION_TYPE_MAP = new HashMap<>();

    private static final Map<Integer, String> PROTOCOL_EXCEPTION_TYPE_MAP = new HashMap<>();

    private static final Map<Integer, String> APPLICATION_EXCEPTION_TYPE_MAP = new HashMap<>();

    private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();

    private static final Map<String, Integer> EXCEPTION_COUNT_MAP = new HashMap<>();

    private static final Map<String, Integer> EXCEPTION_MAP = new HashMap<>();

    private static final int TAB_WIDTH = 50;

    static {
        TRANSPORT_EXCEPTION_TYPE_MAP.put(0, "Unknown");
        TRANSPORT_EXCEPTION_TYPE_MAP.put(1, "Socket not open");
        TRANSPORT_EXCEPTION_TYPE_MAP.put(2, "Socket already open(connected)");
        TRANSPORT_EXCEPTION_TYPE_MAP.put(3, "Time out");
        TRANSPORT_EXCEPTION_TYPE_MAP.put(4, "End of file! Check connection or protocol type");
        TRANSPORT_EXCEPTION_TYPE_MAP.put(5, "Corrupted data! Maybe read a negative frame size or frame size larger " +
                "than max_length");

        PROTOCOL_EXCEPTION_TYPE_MAP.put(0, "Unknown");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(1, "Required field types must be consistent");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(2, "Negative size");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(3, "Size limit");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(4, "Bad version! Maybe caused by protocol type or read strict");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(5, "This protocol does not support (yet)");
        PROTOCOL_EXCEPTION_TYPE_MAP.put(6, "Depth limit");

        APPLICATION_EXCEPTION_TYPE_MAP.put(0, "Unknown");
        APPLICATION_EXCEPTION_TYPE_MAP.put(1, "Unknown method");
        APPLICATION_EXCEPTION_TYPE_MAP.put(2, "Invalid message type");
        APPLICATION_EXCEPTION_TYPE_MAP.put(3, "Wrong method name");
        APPLICATION_EXCEPTION_TYPE_MAP.put(4, "Bad sequence id");
        APPLICATION_EXCEPTION_TYPE_MAP.put(5, "Missing result");
        APPLICATION_EXCEPTION_TYPE_MAP.put(6, "Internal error");
        APPLICATION_EXCEPTION_TYPE_MAP.put(7, "Protocol error");
        APPLICATION_EXCEPTION_TYPE_MAP.put(8, "Invalid transform");
        APPLICATION_EXCEPTION_TYPE_MAP.put(9, "Invalid protocol");
        APPLICATION_EXCEPTION_TYPE_MAP.put(10, "Unsupported client type");

        EXCEPTION_COUNT_MAP.put("APPLICATION_EXCEPTION", 0);
        EXCEPTION_COUNT_MAP.put("PROTOCOL_EXCEPTION", 0);
        EXCEPTION_COUNT_MAP.put("TRANSPORT_EXCEPTION", 0);
        EXCEPTION_COUNT_MAP.put("OTHERS", 0);
    }

    private int min = Integer.MAX_VALUE;
    private int max = Integer.MIN_VALUE;
    private int p99 = Integer.MAX_VALUE;
    private int p95 = Integer.MAX_VALUE;
    private int p90 = Integer.MAX_VALUE;
    private int p75 = Integer.MAX_VALUE;
    private int p50 = Integer.MAX_VALUE;
    private double sucRateWCS = 0;
    private double sucRateCCS = 0;
    private double latency = 0;
    private AtomicInteger connects = new AtomicInteger(0);
    private AtomicInteger requests = new AtomicInteger(0);
    private int responses = 0;
    private int timeTaken = 0;
    private Map<Integer, Integer> timeAndCounts = new ConcurrentHashMap<>();

    Statistic(int interval) {
        if (interval <= 0) {
            interval = 1;
        }
        EXECUTOR.scheduleAtFixedRate(() ->
                        ConsolePrinter.say("\tTotal {} (Connect: {}, Send: {}) requests",
                                this.requests.get() + this.connects.get(), this.connects.get(), this.requests.get()),
                interval + 1,
                interval,
                TimeUnit.SECONDS);
    }

    private static String formatStr(String str) {
        int strLen;
        if (str == null) {
            strLen = 0;
        } else {
            strLen = str.length();
        }

        if (strLen == TAB_WIDTH) {
            return str;
        } else if (strLen < TAB_WIDTH) {
            int temp = TAB_WIDTH - strLen;
            String tem = "";
            for (int i = 0; i < temp; i++) {
                tem = tem + " ";
            }
            return str + tem;
        } else {
            return str.substring(0, TAB_WIDTH);
        }
    }

    private int[] bucketSort(int max, int min, int interval, Map<Integer, Integer> timeAndCounts) {
        int[] bucket;
        if (interval > 1) {
            bucket = new int[10000];
            for (Map.Entry<Integer, Integer> entry : timeAndCounts.entrySet()) {
                bucket[(entry.getKey() - min) / interval] += entry.getValue();
            }
        } else {
            bucket = new int[max - min + 1];
            for (Map.Entry<Integer, Integer> entry : timeAndCounts.entrySet()) {
                bucket[entry.getKey() - min] += entry.getValue();
            }
        }
        return bucket;
    }

    private void calculatePercentage() {
        if (this.responses == 0) {
            return;
        }
        if (this.timeAndCounts.size() == 1) {
            for (Map.Entry<Integer, Integer> entry : timeAndCounts.entrySet()) {
                this.p50 = this.p75 = this.p90 = this.p95 = this.p99 = entry.getValue();
            }
            return;
        }

        int sum = 0;
        int interval = (this.max - this.min) / 10000 + 1;
        int[] bucket = bucketSort(this.max, this.min, interval, this.timeAndCounts);
        for (int i = 0; i < bucket.length; i++) {
            sum += bucket[i];
            if (this.p50 == Integer.MAX_VALUE && sum >= this.responses * 0.50) {
                this.p50 = this.min + i * interval;
            }
            if (this.p75 == Integer.MAX_VALUE && sum >= this.responses * 0.75) {
                this.p75 = this.min + i * interval;
            }
            if (this.p90 == Integer.MAX_VALUE && sum >= this.responses * 0.90) {
                this.p90 = this.min + i * interval;
            }
            if (this.p95 == Integer.MAX_VALUE && sum >= this.responses * 0.95) {
                this.p95 = this.min + i * interval;
            }
            if (this.p99 == Integer.MAX_VALUE && sum >= this.responses * 0.99) {
                this.p99 = this.min + i * interval;
                break;
            }
        }
    }

    void onSend() {
        this.requests.getAndIncrement();
        this.connects.getAndDecrement();
    }

    synchronized void onReceived(int time) {
        if (this.max < time) {
            this.max = time;
        }
        if (this.min > time) {
            this.min = time;
        }
        this.timeTaken += time;
        this.responses += 1;
        Integer count = this.timeAndCounts.get(time);
        if (count == null) {
            count = 0;
        }
        this.timeAndCounts.put(time, ++count);
    }

    synchronized void onError(Exception e) {
        if (e instanceof InvocationTargetException) {
            Throwable throwable = ((InvocationTargetException) e).getTargetException();
            if (throwable instanceof TTransportException) {
                int count = EXCEPTION_COUNT_MAP.get("TRANSPORT_EXCEPTION");
                EXCEPTION_COUNT_MAP.put("TRANSPORT_EXCEPTION", ++count);
                int type = ((TTransportException) throwable).getType();
                String msg = TRANSPORT_EXCEPTION_TYPE_MAP.get(type);
                statisticalErrCount("TTransportException[" + type + ", Msg: " + msg + "]");
                onError(throwable, msg);
            }
            if (throwable instanceof TProtocolException) {
                int count = EXCEPTION_COUNT_MAP.get("PROTOCOL_EXCEPTION");
                EXCEPTION_COUNT_MAP.put("PROTOCOL_EXCEPTION", ++count);
                int type = ((TProtocolException) throwable).getType();
                String msg = PROTOCOL_EXCEPTION_TYPE_MAP.get(type);
                statisticalErrCount("TProtocolException[" + type + ", Msg: " + msg + "]");
                onError(throwable, msg);
            }
            if (throwable instanceof TApplicationException) {
                int count = EXCEPTION_COUNT_MAP.get("APPLICATION_EXCEPTION");
                EXCEPTION_COUNT_MAP.put("APPLICATION_EXCEPTION", ++count);
                int type = ((TApplicationException) throwable).getType();
                String msg = APPLICATION_EXCEPTION_TYPE_MAP.get(type);
                statisticalErrCount("TApplicationException[" + type + ", Msg: " + msg + "]");
                onError(throwable, msg);
            }
        } else {
            int count = EXCEPTION_COUNT_MAP.get("OTHERS");
            count++;
            EXCEPTION_COUNT_MAP.put("OTHERS", count);
            statisticalErrCount(e.getMessage());
            onError(e, null);
        }
    }

    private synchronized void onError(Throwable e, String msg) {
        if (Strings.isBlank(msg)) {
            LOGGER.error("ErrMsg: {}", e.getMessage() == null ? e.getStackTrace()[0].toString() : e.getMessage());
        } else {
            LOGGER.error("ErrMsg: {} , Maybe caused by {}",
                    e.getMessage() == null ?
                            e.getStackTrace()[0].toString() :
                            e.getMessage(),
                    msg);
        }
    }

    private void statisticalErrCount(String errorMsg) {
        Integer msgCount = EXCEPTION_MAP.get(errorMsg);
        if (msgCount == null) {
            msgCount = 0;
        }
//        if (msgCount > 100) {
//            LOGGER.info("There are too many mistakes({}). Please check them first!", errorMsg);
//            System.exit(1);
//        }
        EXCEPTION_MAP.put(errorMsg, ++msgCount);
    }

    void onStop() {
        EXECUTOR.shutdown();
        // 计算分位耗时
        this.calculatePercentage();
        // 计算成功率
        if (this.requests.get() != 0) {
            this.sucRateWCS = (double) this.responses / this.requests.get() * 100;
            this.sucRateWCS = (double) ((int) (this.sucRateWCS * 100)) / 100;
        }

        this.sucRateCCS = (double) this.responses / (this.requests.get() + this.connects.get()) * 100;
        this.sucRateCCS = (double) ((int) (this.sucRateCCS * 100)) / 100;

        // 计算耗时
        if (this.responses != 0) {
            this.latency = (double) this.timeTaken / this.responses;
            this.latency = (double) ((int) (this.latency * 100)) / 100;
        }
        // 输出报告
        ConsolePrinter.say(this.toString());
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("\tFinished\n")
                .append(formatStr("Time taken for successful requests: "))
                .append((double) this.timeTaken / Constants.TIME_CONVERT_BASE)
                .append(" [seconds]\n")
                .append(formatStr("Total: "))
                .append(this.connects.get() + this.requests.get())
                .append("\n")
                .append(formatStr("On connection stat: "))
                .append(this.connects.get())
                .append("\n")
                .append(formatStr("Send: "))
                .append(this.requests.get())
                .append("\n")
                .append(formatStr("Receive: "))
                .append(this.responses)
                .append("\n")
                .append(formatStr("Failed: "))
                .append(this.requests.get() - this.responses + this.connects.get())
                .append("\n");
        if (EXCEPTION_MAP.size() > 0) {
            for (Map.Entry<String, Integer> entry : EXCEPTION_MAP.entrySet()) {
                stringBuilder.append("\t").append("Exception: ").append(entry.getKey()).append(", Counts: ")
                        .append(entry.getValue())
                        .append("\n");
            }
        }
        stringBuilder.append(formatStr("Success rate without connection stat: "))
                .append(this.sucRateWCS)
                .append(" [%]\n")
                .append(formatStr("Success rate contains connection stat: "))
                .append(this.sucRateCCS)
                .append(" [%]\n")
                .append(formatStr("Time per request: "))
                .append(this.latency == 0 ? "--" : this.latency)
                .append(" [ms] \n")
                .append(formatStr("Minimum time taken "))
                .append(this.min == Integer.MAX_VALUE ? "--" : this.min)
                .append(" [ms]\n")
                .append(formatStr("Maximum time taken "))
                .append(this.max == Integer.MIN_VALUE ? "--" : this.max)
                .append(" [ms]\n")
                .append("Percentage of the requests served within a certain time (ms)\n ")
                .append("\t50% ")
                .append(this.p50 == Integer.MAX_VALUE ? "--" : this.p50)
                .append("\n")
                .append("\t75% ")
                .append(this.p75 == Integer.MAX_VALUE ? "--" : this.p75)
                .append("\n")
                .append("\t90% ")
                .append(this.p90 == Integer.MAX_VALUE ? "--" : this.p90)
                .append("\n")
                .append("\t95% ")
                .append(this.p95 == Integer.MAX_VALUE ? "--" : this.p95)
                .append("\n")
                .append("\t99% ")
                .append(this.p99 == Integer.MAX_VALUE ? "--" : this.p99);
        return stringBuilder.toString();
    }

    void onConnect() {
        this.connects.getAndIncrement();
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/utils/ReflectUtils.java<|end_filename|>
package com.didiglobal.pressir.thrift.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.TypeUtils;
import org.apache.logging.log4j.util.Strings;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * @ClassName ReflectUtils
 * @Description 工具类
 * @Author pressir
 * @Date 2019-09-03 11:32
 */
public class ReflectUtils {

    public static Class<?> findInnerClass(Class<?> clazz, String name) throws ClassNotFoundException {
        Class<?>[] innerClasses = clazz.getClasses();
        for (Class innerClass : innerClasses) {
            if (innerClass.getSimpleName().equals(name)) {
                return innerClass;
            }
        }
        throw new ClassNotFoundException("inner class(" + clazz.getName() + '$' + name + ") is invalid");
    }

    public static Method findMethod(Class<?> clazz, String name) throws NoSuchMethodException {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(name)) {
                return method;
            }
        }
        throw new NoSuchMethodException("method(" + clazz.getName() + '.' + name + ") is invalid");
    }

    public static Object[] castArgs(Method method, String... args) {
        int parameterCount = method.getParameterCount();
        if (method.getParameterCount() == 0) {
            if (args == null || args.length == 0) {
                return new Object[0];
            }
            throw new IllegalArgumentException("invalid args. expect 0 parameters, " +
                    "actual got " + args.length);
        }
        if (args == null) {
            throw new IllegalArgumentException("invalid args. expect " + parameterCount + " parameters, " +
                    "actual got 0");
        }
        if (args.length < parameterCount) {
            throw new IllegalArgumentException("invalid args. expect " + parameterCount + " parameters, " +
                    "actual got " + args.length);
        }
        if (args.length > parameterCount) {
            for (int i = parameterCount; i < args.length; i++) {
                if (Strings.isNotBlank(args[i])) {
                    throw new IllegalArgumentException("invalid args. expect " + parameterCount + " parameters, " +
                            "actual got " + args.length);
                }
            }
        }
        Object[] arguments = new Object[parameterCount];
        Type[] parameterTypes = method.getGenericParameterTypes();
        for (int i = 0; i < parameterCount; i++) {
            arguments[i] = cast(args[i], parameterTypes[i]);
        }
        return arguments;
    }

    public static <T> T cast(Object obj, Type type) {
        if (obj == null) {
            return null;
        }
        if (type == String.class) {
            return (T) obj.toString();
        }
        if (type == byte.class || type == Byte.class) {
            return (T) TypeUtils.castToByte(obj);
        }
        if (type == short.class || type == Short.class) {
            return (T) TypeUtils.castToShort(obj);
        }
        if (type == int.class || type == Integer.class) {
            return (T) TypeUtils.castToInt(obj);
        }
        if (type == long.class || type == Long.class) {
            return (T) TypeUtils.castToLong(obj);
        }
        if (type == float.class || type == Float.class) {
            return (T) TypeUtils.castToFloat(obj);
        }
        if (type == double.class || type == Double.class) {
            return (T) TypeUtils.castToDouble(obj);
        }
        if (type == char.class || type == Character.class) {
            return (T) TypeUtils.castToChar(obj);
        }
        if (type == boolean.class || type == Boolean.class) {
            return (T) TypeUtils.castToBoolean(obj);
        }
        if (type == BigDecimal.class) {
            return (T) TypeUtils.castToBigDecimal(obj);
        }
        if (type == BigInteger.class) {
            return (T) TypeUtils.castToBigInteger(obj);
        }
        return JSON.parseObject(obj.toString(), type);
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/executor/ConcurrencyExecutor.java<|end_filename|>
package com.didiglobal.pressir.thrift.executor;

import com.didiglobal.pressir.thrift.constant.Constants;
import com.didiglobal.pressir.thrift.generator.Generator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.IntSupplier;

/**
 * @ClassName ConcurrencyExecutor
 * @Description 并发执行器
 * @Author pressir
 * @Date 2019-09-02 14:47
 */
public class ConcurrencyExecutor extends PressureExecutor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrencyExecutor.class);

    private volatile ScheduledFuture<?> future;

    private volatile int timestamp;

    ConcurrencyExecutor(Generator generator, IntSupplier concurrency) {
        super(concurrency, generator, newPreparer(), newInitExecutor());
    }

    private static ScheduledThreadPoolExecutor newPreparer() {
        return new ScheduledThreadPoolExecutor(
                1,
                new CustomThreadFactory("preparer", Thread.MAX_PRIORITY));
    }

    private static ThreadPoolExecutor newInitExecutor() {
        return new ThreadPoolExecutor(
                1,
                1,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(),
                new CustomThreadFactory("executor", Thread.MAX_PRIORITY));
    }

    @Override
    public final void start(long delay) {
        if (this.future == null) {
            synchronized (this) {
                if (this.shutdown) {
                    throw new RuntimeException("Executor has been shutdown");
                }
                if (this.future == null) {
                    this.future = this.preparer.scheduleWithFixedDelay(
                            this::prepare,
                            Math.max(delay, 1) * 1000,
                            1,
                            TimeUnit.MILLISECONDS);
                    this.await();
                }
            }
        }
    }

    @Override
    protected final void cancel() {
        if (this.future != null) {
            synchronized (this) {
                if (this.future != null) {
                    this.future.cancel(true);
                    this.future = null;
                }
            }
        }
    }

    /**
     * Prepare tasks
     */
    private void prepare() {
        for (; ; ) {
            int timestamp = (int) (System.currentTimeMillis() / Constants.TIME_CONVERT_BASE);
            int threadNums = this.getLimit();
            if (timestamp > this.timestamp) {
                this.timestamp = timestamp;
                LOGGER.debug("Stat: executor(core={},maximum={},workers={},queue={},active={},completed={}), Limit={}",
                        this.executor.getCorePoolSize(),
                        this.executor.getMaximumPoolSize(),
                        this.executor.getPoolSize(),
                        this.executor.getQueue().size(),
                        this.executor.getActiveCount(),
                        this.executor.getCompletedTaskCount(),
                        threadNums);

            }
            if (threadNums <= 0) {
                this.executor.purge();
                return;
            }
            if (threadNums != this.executor.getCorePoolSize()) {
                this.setPoolSize(threadNums);
            }
            int batchSize = Math.max(threadNums, 10);
            int queueSize = this.executor.getQueue().size();
            if (queueSize > batchSize / 2) {
                break;
            }
            long beginTime = System.nanoTime();
            List<Runnable> tasks;
            try {
                tasks = this.generator.generate(batchSize);
            } catch (Exception e) {
                LOGGER.error("generate tasks error: {}, {}", e.getMessage(), e);
                break;
            }
            long endTime = System.nanoTime();
            LOGGER.debug("submit tasks: {}, latency: {} ns. Current nThreads: {}, queueSize: {}",
                    tasks.size(),
                    (endTime - beginTime),
                    threadNums,
                    queueSize);
            for (Runnable task : tasks) {
                if (task == null) {
                    continue;
                }
                this.executor.submit(task);
            }
        }
    }

    /**
     * set concurrent threads
     *
     * @param threadNums
     */
    private void setPoolSize(int threadNums) {
        if (threadNums <= 0) {
            throw new IllegalArgumentException("input pool size " + threadNums + " must not be lte 0");
        }
        synchronized (this) {
            int current = this.executor.getCorePoolSize();
            if (current == threadNums) {
                return;
            }
            LOGGER.debug("pool size(core={}, max={}) change to {}!",
                    current,
                    this.executor.getMaximumPoolSize(),
                    threadNums);
            if (current < threadNums) {
                this.executor.setMaximumPoolSize(threadNums);
                this.executor.setCorePoolSize(threadNums);
            } else {
                this.executor.setCorePoolSize(threadNums);
                this.executor.setMaximumPoolSize(threadNums);
            }
        }
    }
}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/context/InvocationContextTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;

import org.junit.Test;

import java.io.File;

public class InvocationContextTest {

    @Test
    public void shouldReturnTaskGenerator() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        File thriftConf = new File(classLoader.getResource("thrift.conf").getFile());
        String uri = "thrift://127.0.0.1:8090/Soda/getInfos?{\"shopId\":\"11\",\"status\":\"OPEN\"}";
        InvocationContext conf = new InvocationContext(thriftConf, uri);
        conf.getTaskGenerator();
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/load/DurationParser.java<|end_filename|>
package com.didiglobal.pressir.thrift.load;

import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;

import static com.didiglobal.pressir.thrift.constant.Constants.PATTERN;

/**
 * @ClassName DurationParser
 * @Description 时长转换器
 * @Author pressir
 * @Date 2019-09-16 10:59
 */
public class DurationParser {
    public static int parse(String duration) {
        Matcher m = PATTERN.matcher(duration);
        if (!m.matches() || m.groupCount() < 2) {
            throw new IllegalArgumentException("timeUnit error! " +
                    "s means second, " +
                    "m means minute, " +
                    "h means hour, " +
                    "d means day!");
        }

        int time = Integer.parseInt(m.group(1));
        String unit = m.group(2);
        switch (unit) {
            case "":
            case "s":
            case "second":
            case "seconds":
                return time;
            case "m":
            case "minute":
            case "minutes":
                return (int) TimeUnit.MINUTES.toSeconds(time);
            case "h":
            case "hour":
            case "hours":
                return (int) TimeUnit.HOURS.toSeconds(time);
            case "d":
            case "day":
            case "days":
                return (int) TimeUnit.DAYS.toSeconds(time);
            default:
                throw new IllegalArgumentException("duration format error");
        }
    }
}


<|start_filename|>src/test/java/com/pressir/idl/service/Service.java<|end_filename|>
package com.pressir.idl.service;

import com.pressir.idl.Info;
import com.pressir.idl.Shop;
import com.pressir.idl.ShopStatus;
import com.pressir.idl.Soda;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;

import java.util.Collections;
import java.util.List;

/**
 * @ClassName Service
 * @Description TODO
 * @Author didi
 * @Date 2019-09-09 15:17
 */
public class Service {

    public static void main(String[] args) throws TTransportException {
        run();
    }
    public static void run() throws TTransportException {
        TNonblockingServerSocket tNonblockingServerTransport = new TNonblockingServerSocket(8090);
        Impl impl = new Impl();
        Soda.Processor processor = new Soda.Processor<>(impl);
        TProtocolFactory factory = TCompactProtocol::new;
        THsHaServer.Args args1 = new THsHaServer.Args(tNonblockingServerTransport);
        args1.protocolFactory(factory);
        args1.processor(processor);
        THsHaServer tHsHaServer = new THsHaServer(args1);
        System.out.println("server start");
        tHsHaServer.serve();
    }

    public static class Impl implements Soda.Iface {
        @Override
        public ShopStatus getShopStatus(String shopId) {

            Shop shop = new Shop();
            shop.setShopId(shopId);
            shop.setStatus(ShopStatus.OPEN);
            return shop.getStatus();
        }

        @Override
        public List<Info> getInfos(Shop shop) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (shop.getStatus() == ShopStatus.CLOSE) {
                return null;
            }
            Info info = new Info();
            info.setName("info");
            info.setPrice(64L);
            info.setShopId(shop.shopId);
            return Collections.singletonList(info);
        }
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/executor/PressureExecutor.java<|end_filename|>
package com.didiglobal.pressir.thrift.executor;

import com.didiglobal.pressir.thrift.generator.Generator;

import java.io.Closeable;
import java.util.Objects;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.IntSupplier;

/**
 * @ClassName PressureExecutor
 * @Description 压力执行器
 * @Author pressir
 * @Date 2019-09-02 14:43
 */
public abstract class PressureExecutor implements Closeable {
    /**
     * Task generator
     */
    final Generator generator;
    /**
     * Task preparer
     */
    final ScheduledThreadPoolExecutor preparer;
    /**
     * Task executor
     */
    final ThreadPoolExecutor executor;
    /**
     * Pressure Getter
     */
    private final IntSupplier pressureGetter;
    volatile boolean shutdown = false;

    PressureExecutor(
            IntSupplier pressureGetter,
            Generator generator,
            ScheduledThreadPoolExecutor preparer,
            ThreadPoolExecutor executor) {
        this.pressureGetter = Objects.requireNonNull(pressureGetter);
        this.generator = Objects.requireNonNull(generator);
        this.preparer = Objects.requireNonNull(preparer);
        this.executor = Objects.requireNonNull(executor);
    }

    public static ConcurrencyExecutor concurrency(Generator generator, IntSupplier concurrency) {
        return new ConcurrencyExecutor(generator, concurrency);
    }

    public static ThroughputExecutor throughput(Generator generator, IntSupplier throughput) {
        return new ThroughputExecutor(generator, throughput);
    }

    /**
     * start the pressure after delay seconds
     *
     * @param delay
     */
    public abstract void start(long delay);

    /**
     * cancel the pressure
     */
    protected abstract void cancel();

    @Override
    public synchronized void close() {
        try {
            this.cancel();
        } catch (Exception ignored) {
        }
        this.shutdown = true;
        this.executor.shutdownNow();
        this.preparer.shutdownNow();
    }

    final int getLimit() {
        int limit = this.pressureGetter.getAsInt();
        if (limit < 0) {
            synchronized (this) {
                this.notify();
            }
        }
        return limit;
    }

    void await() {
        do {
            synchronized (this) {
                try {
                    this.wait();
                } catch (InterruptedException ignored) {
                }
            }
        } while (this.pressureGetter.getAsInt() >= 0);
        this.cancel();
    }
}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/context/CustomClassLoaderTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;


import org.apache.thrift.TServiceClient;
import org.junit.Assert;
import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class CustomClassLoaderTest {

    @Test
    public void shouldReturnTServiceClient() throws IOException, ClassNotFoundException {
        File jarFile = new File(this.getClass().getClassLoader().getResource("base-1.0-SNAPSHOT.jar").getFile());
        CustomClassLoader classLoader = new CustomClassLoader(jarFile);
        Class<?> clazz = classLoader.loadClass("Soda$Client");
        Assert.assertTrue(TServiceClient.class.isAssignableFrom(clazz));
    }

    @Test(expected = ClassNotFoundException.class)
    public void shouldThrowExceptionForInvalidClass() throws IOException, ClassNotFoundException {
        File jarFile = new File(this.getClass().getClassLoader().getResource("base-1.0-SNAPSHOT.jar").getFile());
        CustomClassLoader classLoader = new CustomClassLoader(jarFile);
        classLoader.loadClass("ABC");
    }

    @Test(expected = NullPointerException.class)
    public void shouldThrowExceptionForNullFile() throws IOException {
        new CustomClassLoader(null);
    }

    @Test(expected = FileNotFoundException.class)
    public void shouldThrowExceptionForInvalidFile() throws IOException {
        File jarFile = new File("xxx");
        new CustomClassLoader(jarFile);
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/context/ContextParser.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;

import com.didiglobal.pressir.thrift.base.transport.TFramedTransportFactory;
import com.didiglobal.pressir.thrift.base.transport.TSocketFactory;
import com.didiglobal.pressir.thrift.base.transport.TTransportFactory;
import com.didiglobal.pressir.thrift.utils.ReflectUtils;
import org.apache.logging.log4j.util.Strings;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.protocol.TSimpleJSONProtocol;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;

/**
 * @ClassName ContextParser
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:09
 */
public class ContextParser {

    public static TTransportFactory parseTransportFactory(String define) {
        return parse(define, ContextParser::newTransportFactory);
    }

    static TProtocolFactory parseProtocolFactory(String define) {
        return parse(define, ContextParser::newProtocolFactory);
    }

    private static TTransportFactory newTransportFactory(String name, Map<String, String> attrs) {
        if (TSocket.class.getSimpleName().equals(name)) {
            return new TSocketFactory(attrs);
        }
        if (TFramedTransport.class.getSimpleName().equals(name)) {
            return new TFramedTransportFactory(attrs);
        }
        throw new IllegalArgumentException("Unsupported transport: " + name);
    }

    private static TProtocolFactory newProtocolFactory(String name, Map<String, String> attrs) {
        if (TBinaryProtocol.class.getSimpleName().equals(name)) {
            return new TBinaryProtocol.Factory();
        }
        if (TCompactProtocol.class.getSimpleName().equals(name)) {
            return new TCompactProtocol.Factory();
        }
        if (TTupleProtocol.class.getSimpleName().equals(name)) {
            return new TTupleProtocol.Factory();
        }
        if (TJSONProtocol.class.getSimpleName().equals(name)) {
            return new TJSONProtocol.Factory();
        }
        if (TSimpleJSONProtocol.class.getSimpleName().equals(name)) {
            return new TSimpleJSONProtocol.Factory();
        }
        throw new IllegalArgumentException();
    }

    public static void setField(Object obj, Map<String, String> attrs) {
        if (attrs == null || attrs.isEmpty()) {
            return;
        }
        for (Field field : obj.getClass().getDeclaredFields()) {
            String name = field.getName();
            int lastIndex = name.length() - 1;
            if (name.charAt(lastIndex) != '_') {
                continue;
            }
            String s = attrs.get(name.substring(0, lastIndex));
            if (s == null) {
                continue;
            }
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            try {
                field.set(obj, ReflectUtils.cast(s, field.getGenericType()));
            } catch (IllegalAccessException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
        }
    }

    private static <T> T parse(String define, BiFunction<String, Map<String, String>, T> mapper) {
        int left = define.indexOf('(');
        if (left < 0) {
            return mapper.apply(trim(define, define.length()), Collections.emptyMap());
        }
        int right = define.lastIndexOf(')');
        if (right < left) {
            throw new IllegalArgumentException();
        }

        int split = 0;
        StringBuilder sb = new StringBuilder();
        Map<String, String> attrs = new HashMap<>();
        for (int i = left + 1, depth = 0; i < right; i++) {
            char ch = define.charAt(i);
            if (ch == ' ') {
                continue;
            }
            if (ch == ',') {
                if (depth == 0) {
                    putAttr(attrs, sb, split);
                    sb.setLength(0);
                    split = 0;
                    continue;
                }
            }
            if (ch == '(') {
                depth++;
            } else if (ch == ')') {
                depth--;
                if (depth < 0) {
                    throw new IllegalArgumentException();
                }
            } else if (ch == '=') {
                if (split == 0) {
                    split = sb.length();
                }
            }
            sb.append(ch);
        }
        if (sb.length() > 0) {
            putAttr(attrs, sb, split);
        }
        return mapper.apply(trim(define, left), attrs);
    }

    private static String trim(String str, int end) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < end; i++) {
            char ch = str.charAt(i);
            if (ch == ' ') {
                continue;
            }
            sb.append(ch);
        }
        return sb.toString();
    }

    private static void putAttr(Map<String, String> attrs, StringBuilder sb, int split) {
        if (split <= 0) {
            throw new IllegalArgumentException();
        }
        attrs.put(sb.substring(0, split), sb.substring(split + 1));
    }
}



<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/load/PressureTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.load;

import org.junit.Assert;
import org.junit.Test;


public class PressureTest {

    @Test
    public void shouldReturnQuantityWherePressureDurationLtGiven() {
        Pressure pressure = new Pressure(10, "100");
        Assert.assertEquals(10, pressure.getCurrentQuantity());
    }

    @Test
    public void shouldReturnNegativeWherePressureDurationGtGiven() throws InterruptedException {
        Pressure pressure = new Pressure(10, "1");
        Thread.sleep(2000);
        Assert.assertEquals(-1, pressure.getCurrentQuantity());
    }

}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/base/transport/TFramedTransportFactoryTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.base.transport;

import com.didiglobal.pressir.thrift.context.ContextParser;
import org.junit.Assert;
import org.junit.Test;

public class TFramedTransportFactoryTest {

    @Test
    public void shouldReturnTFramedTransportFactoryDefault() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TFramedTransport");
        Assert.assertTrue(factory instanceof TFramedTransportFactory);
    }

    @Test
    public void shouldReturnTSocketFactoryWithTransportSet() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TFramedTransport(transport=TSocket)");
        Assert.assertTrue(factory instanceof TFramedTransportFactory);
    }

    @Test
    public void shouldReturnTSocketFactoryWithAllFieldsSet() {
        TTransportFactory factory =
                ContextParser.parseTransportFactory("TFramedTransport(transport=TSocket, " + "maxLength=100)");
        Assert.assertTrue(factory instanceof TFramedTransportFactory);
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/executor/ThroughputExecutor.java<|end_filename|>
package com.didiglobal.pressir.thrift.executor;

import com.didiglobal.pressir.thrift.generator.Generator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.IntSupplier;

/**
 * @ClassName ThroughputExecutor
 * @Description QPS执行器
 * @Author pressir
 * @Date 2019-09-02 14:49
 */
public class ThroughputExecutor extends PressureExecutor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ThroughputExecutor.class);

    private final LinkedBlockingQueue<List<Runnable>> queue = new LinkedBlockingQueue<>();

    private final Vector<ScheduledFuture<?>> futures = new Vector<>(2);

    ThroughputExecutor(Generator generator, IntSupplier throughput) {
        super(throughput, generator, newPreparer(), newExecutor());
    }

    private static ScheduledThreadPoolExecutor newPreparer() {
        return new ScheduledThreadPoolExecutor(
                2,
                new CustomThreadFactory("preparer", Thread.MAX_PRIORITY));
    }

    private static ThreadPoolExecutor newExecutor() {
        return new ThreadPoolExecutor(
                0,
                Integer.MAX_VALUE,
                15L,
                TimeUnit.SECONDS,
                new SynchronousQueue<>(),
                new CustomThreadFactory("executor", Thread.MAX_PRIORITY));
    }

    /**
     * Poll task from queue and do execute
     *
     * @param queue
     * @param executor
     */
    private static void execute(LinkedBlockingQueue<List<Runnable>> queue, ExecutorService executor) {
        List<Runnable> tasks = queue.poll();
        if (tasks == null || tasks.isEmpty()) {
            return;
        }
        for (Runnable task : tasks) {
            if (task == null) {
                continue;
            }
            executor.submit(task);
        }
    }

    /**
     * Split and insert elements into queue
     *
     * @param queue
     * @param elements
     */
    private static void offer(LinkedBlockingQueue<List<Runnable>> queue, List<Runnable> elements) {
        if (elements.isEmpty()) {
            return;
        }
        int size = elements.size();
        int sizePerShard = size / 1000;
        int[] ints = splitRemainder(size % 1000);
        int random = new Random().nextInt(1000);
        for (int i = 0, fromIndex = 0, toIndex; i < 1000; i++) {
            int delta = sizePerShard + ints[(i + random) % 1000];
            if (delta == 0) {
                queue.offer(Collections.emptyList());
            } else {
                toIndex = fromIndex + delta;
                queue.offer(elements.subList(fromIndex, toIndex));
                fromIndex = toIndex;
            }
        }
    }

    /**
     * split remainder
     *
     * @param remainder
     * @return
     */
    private static int[] splitRemainder(int remainder) {
        int[] ints = new int[1000];
        if (remainder > 0) {
            float delta = (float) 1000 / remainder;
            for (int i = 0; i < remainder; i++) {
                ints[Math.round(delta * i)] = 1;
            }
        }
        return ints;
    }

    @Override
    public final void start(long delay) {
        if (this.futures.isEmpty()) {
            synchronized (this.futures) {
                if (this.shutdown) {
                    throw new RuntimeException("Executor has been shutdown");
                }
                if (this.futures.isEmpty()) {
                    this.futures.add(this.preparer.scheduleAtFixedRate(
                            this::generate,
                            Math.max(delay - 1, 0),
                            1,
                            TimeUnit.SECONDS));
                    this.futures.add(this.preparer.scheduleAtFixedRate(
                            () -> ThroughputExecutor.execute(this.queue, this.executor),
                            Math.max(delay, 1) * 1000,
                            1,
                            TimeUnit.MILLISECONDS));
                    this.await();
                }
            }
        }
    }

    @Override
    protected final void cancel() {
        if (!this.futures.isEmpty()) {
            synchronized (this.futures) {
                if (!this.futures.isEmpty()) {
                    this.futures.forEach(future -> future.cancel(true));
                    this.futures.clear();
                }
            }
        }
    }

    /**
     * Generate tasks
     */
    private void generate() {
        int num = this.getLimit();
        LOGGER.debug("ThreadPool Stat: executor(core={},maximum={},workers={},queue={},active={},completed={})," +
                        " preparer(core={},maximum={},workers={},queue={},active={},completed={}), Limit={}",
                this.executor.getCorePoolSize(),
                this.executor.getMaximumPoolSize(),
                this.executor.getPoolSize(),
                this.executor.getQueue().size(),
                this.executor.getActiveCount(),
                this.executor.getCompletedTaskCount(),
                this.preparer.getCorePoolSize(),
                this.preparer.getMaximumPoolSize(),
                this.executor.getPoolSize(),
                this.preparer.getQueue().size(),
                this.preparer.getActiveCount(),
                this.preparer.getCompletedTaskCount(),
                num);
        if (num <= 0) {
            return;
        }
        List<Runnable> tasks;
        long beginTime = System.nanoTime();
        try {
            tasks = this.generator.generate(num);
        } catch (Exception e) {
            LOGGER.error("generate tasks error: {}, {}", e.getMessage(), e);
            return;
        }
        long endTime = System.nanoTime();
        LOGGER.debug("prepared tasks: {}, latency: {} ns. current limit: {}",
                tasks.size(),
                (endTime - beginTime),
                num);
        ThroughputExecutor.offer(this.queue, tasks);
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/context/CustomClassLoader.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @ClassName CustomClassLoader
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 22:04
 */
public class CustomClassLoader implements Closeable {
    private final JarFile jarFile;

    private final URLClassLoader classLoader;

    CustomClassLoader(File jarFile) throws IOException {
        if (jarFile == null) {
            throw new NullPointerException("null file");
        }
        if (!jarFile.exists() || !jarFile.isFile()) {
            throw new FileNotFoundException("invalid file: " + jarFile.getPath());
        }
        this.jarFile = new JarFile(jarFile);
        this.classLoader = URLClassLoader.newInstance(
                new URL[]{jarFile.toURI().toURL()},
                URLClassLoader.getSystemClassLoader());
    }

    Class<?> loadClass(String className) throws ClassNotFoundException {
        String classFileName = className.replace('.', File.separatorChar).concat(".class");
        Enumeration<JarEntry> enumeration = jarFile.entries();
        while (enumeration.hasMoreElements()) {
            JarEntry jarEntry = enumeration.nextElement();
            if (jarEntry.isDirectory()) {
                continue;
            }
            String jarEntryName = jarEntry.getName();
            int lengthDiff = jarEntryName.length() - classFileName.length();
            if (lengthDiff < 0) {
                continue;
            } else if (lengthDiff > 0) {
                if (jarEntryName.charAt(lengthDiff - 1) != File.separatorChar) {
                    continue;
                }
                if (!jarEntryName.endsWith(classFileName)) {
                    continue;
                }
            } else {
                if (!jarEntryName.equals(classFileName)) {
                    continue;
                }
            }
            String name = jarEntryName.substring(0, jarEntryName.length() - 6).replace(File.separatorChar, '.');
            return this.classLoader.loadClass(name);
        }
        throw new ClassNotFoundException("invalid class: " + className);
    }

    @Override
    public void close() throws IOException {
        this.classLoader.close();
    }
}


<|start_filename|>src/test/java/com/pressir/idl/Soda.java<|end_filename|>
package com.pressir.idl;

/**
 * Autogenerated by Thrift Compiler (0.11.0)
 * <p>
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *
 * @generated
 */
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2019-09-05")
public class Soda {

    public interface Iface {

        public ShopStatus getShopStatus(java.lang.String shopId) throws org.apache.thrift.TException;

        public java.util.List<Info> getInfos(Shop shop) throws org.apache.thrift.TException;

    }

    public interface AsyncIface {

        public void getShopStatus(
                java.lang.String shopId,
                org.apache.thrift.async.AsyncMethodCallback<ShopStatus> resultHandler)
                throws org.apache.thrift.TException;

        public void getInfos(
                Shop shop,
                org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>> resultHandler)
                throws org.apache.thrift.TException;

    }

    public static class Client extends org.apache.thrift.TServiceClient implements Iface {
        public Client(org.apache.thrift.protocol.TProtocol prot) {
            super(prot, prot);
        }

        public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
            super(iprot, oprot);
        }

        public ShopStatus getShopStatus(java.lang.String shopId) throws org.apache.thrift.TException {
            send_getShopStatus(shopId);
            return recv_getShopStatus();
        }

        public void send_getShopStatus(java.lang.String shopId) throws org.apache.thrift.TException {
            getShopStatus_args args = new getShopStatus_args();
            args.setShopId(shopId);
            sendBase("getShopStatus", args);
        }

        public ShopStatus recv_getShopStatus() throws org.apache.thrift.TException {
            getShopStatus_result result = new getShopStatus_result();
            receiveBase(result, "getShopStatus");
            if (result.isSetSuccess()) {
                return result.success;
            }
            throw new org.apache.thrift.TApplicationException(
                    org.apache.thrift.TApplicationException.MISSING_RESULT,
                    "getShopStatus failed: unknown result");
        }

        public java.util.List<Info> getInfos(Shop shop) throws org.apache.thrift.TException {
            send_getInfos(shop);
            return recv_getInfos();
        }

        public void send_getInfos(Shop shop) throws org.apache.thrift.TException {
            getInfos_args args = new getInfos_args();
            args.setShop(shop);
            sendBase("getInfos", args);
        }

        public java.util.List<Info> recv_getInfos() throws org.apache.thrift.TException {
            getInfos_result result = new getInfos_result();
            receiveBase(result, "getInfos");
            if (result.isSetSuccess()) {
                return result.success;
            }
            throw new org.apache.thrift.TApplicationException(
                    org.apache.thrift.TApplicationException.MISSING_RESULT,
                    "getInfos failed: unknown result");
        }

        public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
            public Factory() {
            }

            public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
                return new Client(prot);
            }

            public Client getClient(
                    org.apache.thrift.protocol.TProtocol iprot,
                    org.apache.thrift.protocol.TProtocol oprot) {
                return new Client(iprot, oprot);
            }
        }

    }

    public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
        public AsyncClient(
                org.apache.thrift.protocol.TProtocolFactory protocolFactory,
                org.apache.thrift.async.TAsyncClientManager clientManager,
                org.apache.thrift.transport.TNonblockingTransport transport) {
            super(protocolFactory, clientManager, transport);
        }

        public void getShopStatus(
                java.lang.String shopId,
                org.apache.thrift.async.AsyncMethodCallback<ShopStatus> resultHandler)
                throws org.apache.thrift.TException {
            checkReady();
            getShopStatus_call method_call =
                    new getShopStatus_call(
                            shopId,
                            resultHandler,
                            this,
                            ___protocolFactory,
                            ___transport);
            this.___currentMethod = method_call;
            ___manager.call(method_call);
        }

        public void getInfos(
                Shop shop,
                org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>> resultHandler)
                throws org.apache.thrift.TException {
            checkReady();
            getInfos_call method_call = new getInfos_call(
                    shop,
                    resultHandler,
                    this,
                    ___protocolFactory,
                    ___transport);
            this.___currentMethod = method_call;
            ___manager.call(method_call);
        }

        public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
            private org.apache.thrift.async.TAsyncClientManager clientManager;
            private org.apache.thrift.protocol.TProtocolFactory protocolFactory;

            public Factory(
                    org.apache.thrift.async.TAsyncClientManager clientManager,
                    org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
                this.clientManager = clientManager;
                this.protocolFactory = protocolFactory;
            }

            public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
                return new AsyncClient(protocolFactory, clientManager, transport);
            }
        }

        public static class getShopStatus_call extends org.apache.thrift.async.TAsyncMethodCall<ShopStatus> {
            private java.lang.String shopId;

            public getShopStatus_call(
                    java.lang.String shopId,
                    org.apache.thrift.async.AsyncMethodCallback<ShopStatus> resultHandler,
                    org.apache.thrift.async.TAsyncClient client,
                    org.apache.thrift.protocol.TProtocolFactory protocolFactory,
                    org.apache.thrift.transport.TNonblockingTransport transport)
                    throws org.apache.thrift.TException {
                super(client, protocolFactory, transport, resultHandler, false);
                this.shopId = shopId;
            }

            public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
                prot.writeMessageBegin(
                        new org.apache.thrift.protocol.TMessage(
                                "getShopStatus",
                                org.apache.thrift.protocol.TMessageType.CALL,
                                0)
                );
                getShopStatus_args args = new getShopStatus_args();
                args.setShopId(shopId);
                args.write(prot);
                prot.writeMessageEnd();
            }

            public ShopStatus getResult() throws org.apache.thrift.TException {
                if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
                    throw new java.lang.IllegalStateException("Method call not finished!");
                }
                org.apache.thrift.transport.TMemoryInputTransport memoryTransport =
                        new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
                org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
                return (new Client(prot)).recv_getShopStatus();
            }
        }

        public static class getInfos_call extends org.apache.thrift.async.TAsyncMethodCall<java.util.List<Info>> {
            private Shop shop;

            public getInfos_call(
                    Shop shop,
                    org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>> resultHandler,
                    org.apache.thrift.async.TAsyncClient client,
                    org.apache.thrift.protocol.TProtocolFactory protocolFactory,
                    org.apache.thrift.transport.TNonblockingTransport transport)
                    throws org.apache.thrift.TException {
                super(client, protocolFactory, transport, resultHandler, false);
                this.shop = shop;
            }

            public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
                prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(
                        "getInfos",
                        org.apache.thrift.protocol.TMessageType.CALL,
                        0)
                );
                getInfos_args args = new getInfos_args();
                args.setShop(shop);
                args.write(prot);
                prot.writeMessageEnd();
            }

            public java.util.List<Info> getResult() throws org.apache.thrift.TException {
                if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
                    throw new java.lang.IllegalStateException("Method call not finished!");
                }
                org.apache.thrift.transport.TMemoryInputTransport memoryTransport =
                        new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
                org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
                return (new Client(prot)).recv_getInfos();
            }
        }

    }

    public static class Processor<I extends Iface>
            extends org.apache.thrift.TBaseProcessor<I>
            implements org.apache.thrift.TProcessor {
        private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(Processor.class.getName());

        public Processor(I iface) {
            super(iface, getProcessMap(
                    new java.util.HashMap<java.lang.String,
                            org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()
            ));
        }

        protected Processor(
                I iface,
                java.util.Map<java.lang.String,
                        org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
            super(iface, getProcessMap(processMap));
        }

        private static <I extends Iface> java.util.Map<java.lang.String,
                org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> getProcessMap(
                java.util.Map<java.lang.String,
                        org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
            processMap.put("getShopStatus", new getShopStatus());
            processMap.put("getInfos", new getInfos());
            return processMap;
        }

        public static class getShopStatus<I extends Iface>
                extends org.apache.thrift.ProcessFunction<I, getShopStatus_args> {
            public getShopStatus() {
                super("getShopStatus");
            }

            public getShopStatus_args getEmptyArgsInstance() {
                return new getShopStatus_args();
            }

            protected boolean isOneway() {
                return false;
            }

            @Override
            protected boolean handleRuntimeExceptions() {
                return false;
            }

            public getShopStatus_result getResult(
                    I iface,
                    getShopStatus_args args)
                    throws org.apache.thrift.TException {
                getShopStatus_result result = new getShopStatus_result();
                result.success = iface.getShopStatus(args.shopId);
                return result;
            }
        }

        public static class getInfos<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getInfos_args> {
            public getInfos() {
                super("getInfos");
            }

            public getInfos_args getEmptyArgsInstance() {
                return new getInfos_args();
            }

            protected boolean isOneway() {
                return false;
            }

            @Override
            protected boolean handleRuntimeExceptions() {
                return false;
            }

            public getInfos_result getResult(I iface, getInfos_args args) throws org.apache.thrift.TException {
                getInfos_result result = new getInfos_result();
                result.success = iface.getInfos(args.shop);
                return result;
            }
        }

    }

    public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
        private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(AsyncProcessor.class.getName());

        public AsyncProcessor(I iface) {
            super(iface, getProcessMap(
                    new java.util.HashMap<
                            java.lang.String,
                            org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
        }

        protected AsyncProcessor(
                I iface,
                java.util.Map<
                        java.lang.String,
                        org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
            super(iface, getProcessMap(processMap));
        }

        private static <I extends AsyncIface> java.util.Map<java.lang.String,
                org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> getProcessMap(
                        java.util.Map<
                                java.lang.String,
                                org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
            processMap.put("getShopStatus", new getShopStatus());
            processMap.put("getInfos", new getInfos());
            return processMap;
        }

        public static class getShopStatus<I extends AsyncIface>
                extends org.apache.thrift.AsyncProcessFunction<I, getShopStatus_args, ShopStatus> {
            public getShopStatus() {
                super("getShopStatus");
            }

            public getShopStatus_args getEmptyArgsInstance() {
                return new getShopStatus_args();
            }

            public org.apache.thrift.async.AsyncMethodCallback<ShopStatus> getResultHandler(
                    final org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) {
                final org.apache.thrift.AsyncProcessFunction fcall = this;
                return new org.apache.thrift.async.AsyncMethodCallback<ShopStatus>() {
                    public void onComplete(ShopStatus o) {
                        getShopStatus_result result = new getShopStatus_result();
                        result.success = o;
                        try {
                            fcall.sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid);
                        } catch (org.apache.thrift.transport.TTransportException e) {
                            _LOGGER.error("TTransportException writing to internal frame buffer", e);
                            fb.close();
                        } catch (java.lang.Exception e) {
                            _LOGGER.error("Exception writing to internal frame buffer", e);
                            onError(e);
                        }
                    }

                    public void onError(java.lang.Exception e) {
                        byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
                        org.apache.thrift.TSerializable msg;
                        getShopStatus_result result = new getShopStatus_result();
                        if (e instanceof org.apache.thrift.transport.TTransportException) {
                            _LOGGER.error("TTransportException inside handler", e);
                            fb.close();
                            return;
                        } else if (e instanceof org.apache.thrift.TApplicationException) {
                            _LOGGER.error("TApplicationException inside handler", e);
                            msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
                            msg = (org.apache.thrift.TApplicationException) e;
                        } else {
                            _LOGGER.error("Exception inside handler", e);
                            msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
                            msg = new org.apache.thrift.TApplicationException(
                                    org.apache.thrift.TApplicationException.INTERNAL_ERROR,
                                    e.getMessage());
                        }
                        try {
                            fcall.sendResponse(fb, msg, msgType, seqid);
                        } catch (java.lang.Exception ex) {
                            _LOGGER.error("Exception writing to internal frame buffer", ex);
                            fb.close();
                        }
                    }
                };
            }

            protected boolean isOneway() {
                return false;
            }

            public void start(I iface,
                              getShopStatus_args args,
                              org.apache.thrift.async.AsyncMethodCallback<ShopStatus> resultHandler)
                    throws org.apache.thrift.TException {
                iface.getShopStatus(args.shopId, resultHandler);
            }
        }

        public static class getInfos<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getInfos_args, java.util.List<Info>> {
            public getInfos() {
                super("getInfos");
            }

            public getInfos_args getEmptyArgsInstance() {
                return new getInfos_args();
            }

            public org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>> getResultHandler(
                    final org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) {
                final org.apache.thrift.AsyncProcessFunction fcall = this;
                return new org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>>() {
                    public void onComplete(java.util.List<Info> o) {
                        getInfos_result result = new getInfos_result();
                        result.success = o;
                        try {
                            fcall.sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid);
                        } catch (org.apache.thrift.transport.TTransportException e) {
                            _LOGGER.error("TTransportException writing to internal frame buffer", e);
                            fb.close();
                        } catch (java.lang.Exception e) {
                            _LOGGER.error("Exception writing to internal frame buffer", e);
                            onError(e);
                        }
                    }

                    public void onError(java.lang.Exception e) {
                        byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
                        org.apache.thrift.TSerializable msg;
                        getInfos_result result = new getInfos_result();
                        if (e instanceof org.apache.thrift.transport.TTransportException) {
                            _LOGGER.error("TTransportException inside handler", e);
                            fb.close();
                            return;
                        } else if (e instanceof org.apache.thrift.TApplicationException) {
                            _LOGGER.error("TApplicationException inside handler", e);
                            msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
                            msg = (org.apache.thrift.TApplicationException) e;
                        } else {
                            _LOGGER.error("Exception inside handler", e);
                            msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
                            msg = new org.apache.thrift.TApplicationException(
                                    org.apache.thrift.TApplicationException.INTERNAL_ERROR,
                                    e.getMessage());
                        }
                        try {
                            fcall.sendResponse(fb, msg, msgType, seqid);
                        } catch (java.lang.Exception ex) {
                            _LOGGER.error("Exception writing to internal frame buffer", ex);
                            fb.close();
                        }
                    }
                };
            }

            protected boolean isOneway() {
                return false;
            }

            public void start(I iface, getInfos_args args,
                              org.apache.thrift.async.AsyncMethodCallback<java.util.List<Info>> resultHandler)
                    throws org.apache.thrift.TException {
                iface.getInfos(args.shop, resultHandler);
            }
        }

    }

    public static class getShopStatus_args
            implements org.apache.thrift.TBase<getShopStatus_args, getShopStatus_args._Fields>,
            java.io.Serializable,
            Cloneable,
            Comparable<getShopStatus_args> {
        // isset id assignments
        public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
        private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
                new org.apache.thrift.protocol.TStruct("getShopStatus_args");
        private static final org.apache.thrift.protocol.TField SHOP_ID_FIELD_DESC =
                new org.apache.thrift.protocol.TField("shopId", org.apache.thrift.protocol.TType.STRING, (short) 1);
        private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY =
                new getShopStatus_argsStandardSchemeFactory();
        private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY =
                new getShopStatus_argsTupleSchemeFactory();

        static {
            java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
            tmpMap.put(_Fields.SHOP_ID,
                    new org.apache.thrift.meta_data.FieldMetaData("shopId", org.apache.thrift.TFieldRequirementType.DEFAULT,
                    new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
            metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
            org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getShopStatus_args.class, metaDataMap);
        }

        public java.lang.String shopId; // required

        public getShopStatus_args() {
        }

        public getShopStatus_args(
                java.lang.String shopId) {
            this();
            this.shopId = shopId;
        }

        /**
         * Performs a deep copy on <i>other</i>.
         */
        public getShopStatus_args(getShopStatus_args other) {
            if (other.isSetShopId()) {
                this.shopId = other.shopId;
            }
        }

        private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
            return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ?
                    STANDARD_SCHEME_FACTORY :
                    TUPLE_SCHEME_FACTORY)
                    .getScheme();
        }

        public getShopStatus_args deepCopy() {
            return new getShopStatus_args(this);
        }

        @Override
        public void clear() {
            this.shopId = null;
        }

        public java.lang.String getShopId() {
            return this.shopId;
        }

        public getShopStatus_args setShopId(java.lang.String shopId) {
            this.shopId = shopId;
            return this;
        }

        public void unsetShopId() {
            this.shopId = null;
        }

        /**
         * Returns true if field shopId is set (has been assigned a value) and false otherwise
         */
        public boolean isSetShopId() {
            return this.shopId != null;
        }

        public void setShopIdIsSet(boolean value) {
            if (!value) {
                this.shopId = null;
            }
        }

        public void setFieldValue(_Fields field, java.lang.Object value) {
            switch (field) {
                case SHOP_ID:
                    if (value == null) {
                        unsetShopId();
                    } else {
                        setShopId((java.lang.String) value);
                    }
                    break;

            }
        }

        public java.lang.Object getFieldValue(_Fields field) {
            switch (field) {
                case SHOP_ID:
                    return getShopId();

            }
            throw new java.lang.IllegalStateException();
        }

        /**
         * Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise
         */
        public boolean isSet(_Fields field) {
            if (field == null) {
                throw new java.lang.IllegalArgumentException();
            }

            switch (field) {
                case SHOP_ID:
                    return isSetShopId();
            }
            throw new java.lang.IllegalStateException();
        }

        @Override
        public boolean equals(java.lang.Object that) {
            if (that == null)
                return false;
            if (that instanceof getShopStatus_args)
                return this.equals((getShopStatus_args) that);
            return false;
        }

        public boolean equals(getShopStatus_args that) {
            if (that == null)
                return false;
            if (this == that)
                return true;

            boolean this_present_shopId = true && this.isSetShopId();
            boolean that_present_shopId = true && that.isSetShopId();
            if (this_present_shopId || that_present_shopId) {
                if (!(this_present_shopId && that_present_shopId))
                    return false;
                if (!this.shopId.equals(that.shopId))
                    return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int hashCode = 1;

            hashCode = hashCode * 8191 + ((isSetShopId()) ? 131071 : 524287);
            if (isSetShopId())
                hashCode = hashCode * 8191 + shopId.hashCode();

            return hashCode;
        }

        @Override
        public int compareTo(getShopStatus_args other) {
            if (!getClass().equals(other.getClass())) {
                return getClass().getName().compareTo(other.getClass().getName());
            }

            int lastComparison = 0;

            lastComparison = java.lang.Boolean.valueOf(isSetShopId()).compareTo(other.isSetShopId());
            if (lastComparison != 0) {
                return lastComparison;
            }
            if (isSetShopId()) {
                lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.shopId, other.shopId);
                if (lastComparison != 0) {
                    return lastComparison;
                }
            }
            return 0;
        }

        public _Fields fieldForId(int fieldId) {
            return _Fields.findByThriftId(fieldId);
        }

        public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
            scheme(iprot).read(iprot, this);
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
            scheme(oprot).write(oprot, this);
        }

        @Override
        public java.lang.String toString() {
            java.lang.StringBuilder sb = new java.lang.StringBuilder("getShopStatus_args(");
            boolean first = true;

            sb.append("shopId:");
            if (this.shopId == null) {
                sb.append("null");
            } else {
                sb.append(this.shopId);
            }
            first = false;
            sb.append(")");
            return sb.toString();
        }

        public void validate() throws org.apache.thrift.TException {
            // check for required fields
            // check for sub-struct validity
        }

        private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
            try {
                write(new org.apache.thrift.protocol.TCompactProtocol(
                        new org.apache.thrift.transport.TIOStreamTransport(out)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, java.lang.ClassNotFoundException {
            try {
                read(new org.apache.thrift.protocol.TCompactProtocol(
                        new org.apache.thrift.transport.TIOStreamTransport(in)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        /**
         * The set of fields this struct contains, along with convenience methods for finding and manipulating them.
         */
        public enum _Fields implements org.apache.thrift.TFieldIdEnum {
            SHOP_ID((short) 1, "shopId");

            private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();

            static {
                for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
                    byName.put(field.getFieldName(), field);
                }
            }

            private final short _thriftId;
            private final java.lang.String _fieldName;

            _Fields(short thriftId, java.lang.String fieldName) {
                _thriftId = thriftId;
                _fieldName = fieldName;
            }

            /**
             * Find the _Fields constant that matches fieldId, or null if its not found.
             */
            public static _Fields findByThriftId(int fieldId) {
                switch (fieldId) {
                    case 1: // SHOP_ID
                        return SHOP_ID;
                    default:
                        return null;
                }
            }

            /**
             * Find the _Fields constant that matches fieldId, throwing an exception
             * if it is not found.
             */
            public static _Fields findByThriftIdOrThrow(int fieldId) {
                _Fields fields = findByThriftId(fieldId);
                if (fields == null)
                    throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
                return fields;
            }

            /**
             * Find the _Fields constant that matches name, or null if its not found.
             */
            public static _Fields findByName(java.lang.String name) {
                return byName.get(name);
            }

            public short getThriftFieldId() {
                return _thriftId;
            }

            public java.lang.String getFieldName() {
                return _fieldName;
            }
        }

        private static class getShopStatus_argsStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getShopStatus_argsStandardScheme getScheme() {
                return new getShopStatus_argsStandardScheme();
            }
        }

        private static class getShopStatus_argsStandardScheme
                extends org.apache.thrift.scheme.StandardScheme<getShopStatus_args> {

            public void read(org.apache.thrift.protocol.TProtocol iprot, getShopStatus_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TField schemeField;
                iprot.readStructBegin();
                while (true) {
                    schemeField = iprot.readFieldBegin();
                    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                        break;
                    }
                    switch (schemeField.id) {
                        case 1: // SHOP_ID
                            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                                struct.shopId = iprot.readString();
                                struct.setShopIdIsSet(true);
                            } else {
                                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                            }
                            break;
                        default:
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                    }
                    iprot.readFieldEnd();
                }
                iprot.readStructEnd();

                // check for required fields of primitive type, which can't be checked in the validate method
                struct.validate();
            }

            public void write(org.apache.thrift.protocol.TProtocol oprot, getShopStatus_args struct)
                    throws org.apache.thrift.TException {
                struct.validate();

                oprot.writeStructBegin(STRUCT_DESC);
                if (struct.shopId != null) {
                    oprot.writeFieldBegin(SHOP_ID_FIELD_DESC);
                    oprot.writeString(struct.shopId);
                    oprot.writeFieldEnd();
                }
                oprot.writeFieldStop();
                oprot.writeStructEnd();
            }

        }

        private static class getShopStatus_argsTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getShopStatus_argsTupleScheme getScheme() {
                return new getShopStatus_argsTupleScheme();
            }
        }

        private static class getShopStatus_argsTupleScheme
                extends org.apache.thrift.scheme.TupleScheme<getShopStatus_args> {

            @Override
            public void write(org.apache.thrift.protocol.TProtocol prot, getShopStatus_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet optionals = new java.util.BitSet();
                if (struct.isSetShopId()) {
                    optionals.set(0);
                }
                oprot.writeBitSet(optionals, 1);
                if (struct.isSetShopId()) {
                    oprot.writeString(struct.shopId);
                }
            }

            @Override
            public void read(org.apache.thrift.protocol.TProtocol prot, getShopStatus_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet incoming = iprot.readBitSet(1);
                if (incoming.get(0)) {
                    struct.shopId = iprot.readString();
                    struct.setShopIdIsSet(true);
                }
            }
        }
    }

    public static class getShopStatus_result
            implements org.apache.thrift.TBase<getShopStatus_result, getShopStatus_result._Fields>,
            java.io.Serializable,
            Cloneable,
            Comparable<getShopStatus_result> {
        // isset id assignments
        public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
        private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
                new org.apache.thrift.protocol.TStruct("getShopStatus_result");
        private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC =
                new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short) 0);
        private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY =
                new getShopStatus_resultStandardSchemeFactory();
        private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY =
                new getShopStatus_resultTupleSchemeFactory();

        static {
            java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap =
                    new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
            tmpMap.put(_Fields.SUCCESS,
                    new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
                    new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, ShopStatus.class)));
            metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
            org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getShopStatus_result.class, metaDataMap);
        }

        /**
         * @see ShopStatus
         */
        public ShopStatus success; // required

        public getShopStatus_result() {
        }

        public getShopStatus_result(
                ShopStatus success) {
            this();
            this.success = success;
        }

        /**
         * Performs a deep copy on <i>other</i>.
         */
        public getShopStatus_result(getShopStatus_result other) {
            if (other.isSetSuccess()) {
                this.success = other.success;
            }
        }

        private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
            return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ?
                    STANDARD_SCHEME_FACTORY :
                    TUPLE_SCHEME_FACTORY)
                    .getScheme();
        }

        public getShopStatus_result deepCopy() {
            return new getShopStatus_result(this);
        }

        @Override
        public void clear() {
            this.success = null;
        }

        /**
         * @see ShopStatus
         */
        public ShopStatus getSuccess() {
            return this.success;
        }

        /**
         * @see ShopStatus
         */
        public getShopStatus_result setSuccess(ShopStatus success) {
            this.success = success;
            return this;
        }

        public void unsetSuccess() {
            this.success = null;
        }

        /**
         * Returns true if field success is set (has been assigned a value) and false otherwise
         */
        public boolean isSetSuccess() {
            return this.success != null;
        }

        public void setSuccessIsSet(boolean value) {
            if (!value) {
                this.success = null;
            }
        }

        public void setFieldValue(_Fields field, java.lang.Object value) {
            switch (field) {
                case SUCCESS:
                    if (value == null) {
                        unsetSuccess();
                    } else {
                        setSuccess((ShopStatus) value);
                    }
                    break;

            }
        }

        public java.lang.Object getFieldValue(_Fields field) {
            switch (field) {
                case SUCCESS:
                    return getSuccess();

            }
            throw new java.lang.IllegalStateException();
        }

        /**
         * Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise
         */
        public boolean isSet(_Fields field) {
            if (field == null) {
                throw new java.lang.IllegalArgumentException();
            }

            switch (field) {
                case SUCCESS:
                    return isSetSuccess();
            }
            throw new java.lang.IllegalStateException();
        }

        @Override
        public boolean equals(java.lang.Object that) {
            if (that == null)
                return false;
            if (that instanceof getShopStatus_result)
                return this.equals((getShopStatus_result) that);
            return false;
        }

        public boolean equals(getShopStatus_result that) {
            if (that == null)
                return false;
            if (this == that)
                return true;

            boolean this_present_success = true && this.isSetSuccess();
            boolean that_present_success = true && that.isSetSuccess();
            if (this_present_success || that_present_success) {
                if (!(this_present_success && that_present_success))
                    return false;
                if (!this.success.equals(that.success))
                    return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int hashCode = 1;

            hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287);
            if (isSetSuccess())
                hashCode = hashCode * 8191 + success.getValue();

            return hashCode;
        }

        @Override
        public int compareTo(getShopStatus_result other) {
            if (!getClass().equals(other.getClass())) {
                return getClass().getName().compareTo(other.getClass().getName());
            }

            int lastComparison = 0;

            lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
            if (lastComparison != 0) {
                return lastComparison;
            }
            if (isSetSuccess()) {
                lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
                if (lastComparison != 0) {
                    return lastComparison;
                }
            }
            return 0;
        }

        public _Fields fieldForId(int fieldId) {
            return _Fields.findByThriftId(fieldId);
        }

        public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
            scheme(iprot).read(iprot, this);
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
            scheme(oprot).write(oprot, this);
        }

        @Override
        public java.lang.String toString() {
            java.lang.StringBuilder sb = new java.lang.StringBuilder("getShopStatus_result(");
            boolean first = true;

            sb.append("success:");
            if (this.success == null) {
                sb.append("null");
            } else {
                sb.append(this.success);
            }
            first = false;
            sb.append(")");
            return sb.toString();
        }

        public void validate() throws org.apache.thrift.TException {
            // check for required fields
            // check for sub-struct validity
        }

        private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
            try {
                write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, java.lang.ClassNotFoundException {
            try {
                read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        /**
         * The set of fields this struct contains, along with convenience methods for finding and manipulating them.
         */
        public enum _Fields implements org.apache.thrift.TFieldIdEnum {
            /**
             * @see ShopStatus
             */
            SUCCESS((short) 0, "success");

            private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();

            static {
                for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
                    byName.put(field.getFieldName(), field);
                }
            }

            private final short _thriftId;
            private final java.lang.String _fieldName;

            _Fields(short thriftId, java.lang.String fieldName) {
                _thriftId = thriftId;
                _fieldName = fieldName;
            }

            /**
             * Find the _Fields constant that matches fieldId, or null if its not found.
             */
            public static _Fields findByThriftId(int fieldId) {
                switch (fieldId) {
                    case 0: // SUCCESS
                        return SUCCESS;
                    default:
                        return null;
                }
            }

            /**
             * Find the _Fields constant that matches fieldId, throwing an exception
             * if it is not found.
             */
            public static _Fields findByThriftIdOrThrow(int fieldId) {
                _Fields fields = findByThriftId(fieldId);
                if (fields == null)
                    throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
                return fields;
            }

            /**
             * Find the _Fields constant that matches name, or null if its not found.
             */
            public static _Fields findByName(java.lang.String name) {
                return byName.get(name);
            }

            public short getThriftFieldId() {
                return _thriftId;
            }

            public java.lang.String getFieldName() {
                return _fieldName;
            }
        }

        private static class getShopStatus_resultStandardSchemeFactory
                implements org.apache.thrift.scheme.SchemeFactory {
            public getShopStatus_resultStandardScheme getScheme() {
                return new getShopStatus_resultStandardScheme();
            }
        }

        private static class getShopStatus_resultStandardScheme
                extends org.apache.thrift.scheme.StandardScheme<getShopStatus_result> {

            public void read(org.apache.thrift.protocol.TProtocol iprot, getShopStatus_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TField schemeField;
                iprot.readStructBegin();
                while (true) {
                    schemeField = iprot.readFieldBegin();
                    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                        break;
                    }
                    switch (schemeField.id) {
                        case 0: // SUCCESS
                            if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                                struct.success = ShopStatus.findByValue(iprot.readI32());
                                struct.setSuccessIsSet(true);
                            } else {
                                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                            }
                            break;
                        default:
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                    }
                    iprot.readFieldEnd();
                }
                iprot.readStructEnd();

                // check for required fields of primitive type, which can't be checked in the validate method
                struct.validate();
            }

            public void write(org.apache.thrift.protocol.TProtocol oprot, getShopStatus_result struct)
                    throws org.apache.thrift.TException {
                struct.validate();

                oprot.writeStructBegin(STRUCT_DESC);
                if (struct.success != null) {
                    oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
                    oprot.writeI32(struct.success.getValue());
                    oprot.writeFieldEnd();
                }
                oprot.writeFieldStop();
                oprot.writeStructEnd();
            }

        }

        private static class getShopStatus_resultTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getShopStatus_resultTupleScheme getScheme() {
                return new getShopStatus_resultTupleScheme();
            }
        }

        private static class getShopStatus_resultTupleScheme
                extends org.apache.thrift.scheme.TupleScheme<getShopStatus_result> {

            @Override
            public void write(org.apache.thrift.protocol.TProtocol prot, getShopStatus_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet optionals = new java.util.BitSet();
                if (struct.isSetSuccess()) {
                    optionals.set(0);
                }
                oprot.writeBitSet(optionals, 1);
                if (struct.isSetSuccess()) {
                    oprot.writeI32(struct.success.getValue());
                }
            }

            @Override
            public void read(org.apache.thrift.protocol.TProtocol prot, getShopStatus_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet incoming = iprot.readBitSet(1);
                if (incoming.get(0)) {
                    struct.success = ShopStatus.findByValue(iprot.readI32());
                    struct.setSuccessIsSet(true);
                }
            }
        }
    }

    public static class getInfos_args
            implements org.apache.thrift.TBase<getInfos_args,
            getInfos_args._Fields>,
            java.io.Serializable,
            Cloneable,
            Comparable<getInfos_args> {
        // isset id assignments
        public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
        private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
                new org.apache.thrift.protocol.TStruct("getInfos_args");
        private static final org.apache.thrift.protocol.TField SHOP_FIELD_DESC =
                new org.apache.thrift.protocol.TField("shop", org.apache.thrift.protocol.TType.STRUCT, (short) 1);
        private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY =
                new getInfos_argsStandardSchemeFactory();
        private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY =
                new getInfos_argsTupleSchemeFactory();

        static {
            java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap =
                    new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
            tmpMap.put(_Fields.SHOP,
                    new org.apache.thrift.meta_data.FieldMetaData("shop", org.apache.thrift.TFieldRequirementType.DEFAULT,
                    new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Shop.class)));
            metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
            org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getInfos_args.class, metaDataMap);
        }

        public Shop shop; // required

        public getInfos_args() {
        }

        public getInfos_args(
                Shop shop) {
            this();
            this.shop = shop;
        }

        /**
         * Performs a deep copy on <i>other</i>.
         */
        public getInfos_args(getInfos_args other) {
            if (other.isSetShop()) {
                this.shop = new Shop(other.shop);
            }
        }

        private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
            return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ?
                    STANDARD_SCHEME_FACTORY :
                    TUPLE_SCHEME_FACTORY)
                    .getScheme();
        }

        public getInfos_args deepCopy() {
            return new getInfos_args(this);
        }

        @Override
        public void clear() {
            this.shop = null;
        }

        public Shop getShop() {
            return this.shop;
        }

        public getInfos_args setShop(Shop shop) {
            this.shop = shop;
            return this;
        }

        public void unsetShop() {
            this.shop = null;
        }

        /**
         * Returns true if field shop is set (has been assigned a value) and false otherwise
         */
        public boolean isSetShop() {
            return this.shop != null;
        }

        public void setShopIsSet(boolean value) {
            if (!value) {
                this.shop = null;
            }
        }

        public void setFieldValue(_Fields field, java.lang.Object value) {
            switch (field) {
                case SHOP:
                    if (value == null) {
                        unsetShop();
                    } else {
                        setShop((Shop) value);
                    }
                    break;

            }
        }

        public java.lang.Object getFieldValue(_Fields field) {
            switch (field) {
                case SHOP:
                    return getShop();

            }
            throw new java.lang.IllegalStateException();
        }

        /**
         * Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise
         */
        public boolean isSet(_Fields field) {
            if (field == null) {
                throw new java.lang.IllegalArgumentException();
            }

            switch (field) {
                case SHOP:
                    return isSetShop();
            }
            throw new java.lang.IllegalStateException();
        }

        @Override
        public boolean equals(java.lang.Object that) {
            if (that == null)
                return false;
            if (that instanceof getInfos_args)
                return this.equals((getInfos_args) that);
            return false;
        }

        public boolean equals(getInfos_args that) {
            if (that == null)
                return false;
            if (this == that)
                return true;

            boolean this_present_shop = true && this.isSetShop();
            boolean that_present_shop = true && that.isSetShop();
            if (this_present_shop || that_present_shop) {
                if (!(this_present_shop && that_present_shop))
                    return false;
                if (!this.shop.equals(that.shop))
                    return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int hashCode = 1;

            hashCode = hashCode * 8191 + ((isSetShop()) ? 131071 : 524287);
            if (isSetShop())
                hashCode = hashCode * 8191 + shop.hashCode();

            return hashCode;
        }

        @Override
        public int compareTo(getInfos_args other) {
            if (!getClass().equals(other.getClass())) {
                return getClass().getName().compareTo(other.getClass().getName());
            }

            int lastComparison = 0;

            lastComparison = java.lang.Boolean.valueOf(isSetShop()).compareTo(other.isSetShop());
            if (lastComparison != 0) {
                return lastComparison;
            }
            if (isSetShop()) {
                lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.shop, other.shop);
                if (lastComparison != 0) {
                    return lastComparison;
                }
            }
            return 0;
        }

        public _Fields fieldForId(int fieldId) {
            return _Fields.findByThriftId(fieldId);
        }

        public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
            scheme(iprot).read(iprot, this);
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
            scheme(oprot).write(oprot, this);
        }

        @Override
        public java.lang.String toString() {
            java.lang.StringBuilder sb = new java.lang.StringBuilder("getInfos_args(");
            boolean first = true;

            sb.append("shop:");
            if (this.shop == null) {
                sb.append("null");
            } else {
                sb.append(this.shop);
            }
            first = false;
            sb.append(")");
            return sb.toString();
        }

        public void validate() throws org.apache.thrift.TException {
            // check for required fields
            // check for sub-struct validity
            if (shop != null) {
                shop.validate();
            }
        }

        private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
            try {
                write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
            try {
                read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        /**
         * The set of fields this struct contains, along with convenience methods for finding and manipulating them.
         */
        public enum _Fields implements org.apache.thrift.TFieldIdEnum {
            SHOP((short) 1, "shop");

            private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();

            static {
                for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
                    byName.put(field.getFieldName(), field);
                }
            }

            private final short _thriftId;
            private final java.lang.String _fieldName;

            _Fields(short thriftId, java.lang.String fieldName) {
                _thriftId = thriftId;
                _fieldName = fieldName;
            }

            /**
             * Find the _Fields constant that matches fieldId, or null if its not found.
             */
            public static _Fields findByThriftId(int fieldId) {
                switch (fieldId) {
                    case 1: // SHOP
                        return SHOP;
                    default:
                        return null;
                }
            }

            /**
             * Find the _Fields constant that matches fieldId, throwing an exception
             * if it is not found.
             */
            public static _Fields findByThriftIdOrThrow(int fieldId) {
                _Fields fields = findByThriftId(fieldId);
                if (fields == null)
                    throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
                return fields;
            }

            /**
             * Find the _Fields constant that matches name, or null if its not found.
             */
            public static _Fields findByName(java.lang.String name) {
                return byName.get(name);
            }

            public short getThriftFieldId() {
                return _thriftId;
            }

            public java.lang.String getFieldName() {
                return _fieldName;
            }
        }

        private static class getInfos_argsStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getInfos_argsStandardScheme getScheme() {
                return new getInfos_argsStandardScheme();
            }
        }

        private static class getInfos_argsStandardScheme extends org.apache.thrift.scheme.StandardScheme<getInfos_args> {

            public void read(org.apache.thrift.protocol.TProtocol iprot, getInfos_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TField schemeField;
                iprot.readStructBegin();
                while (true) {
                    schemeField = iprot.readFieldBegin();
                    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                        break;
                    }
                    switch (schemeField.id) {
                        case 1: // SHOP
                            if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                                struct.shop = new Shop();
                                struct.shop.read(iprot);
                                struct.setShopIsSet(true);
                            } else {
                                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                            }
                            break;
                        default:
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                    }
                    iprot.readFieldEnd();
                }
                iprot.readStructEnd();

                // check for required fields of primitive type, which can't be checked in the validate method
                struct.validate();
            }

            public void write(org.apache.thrift.protocol.TProtocol oprot, getInfos_args struct)
                    throws org.apache.thrift.TException {
                struct.validate();

                oprot.writeStructBegin(STRUCT_DESC);
                if (struct.shop != null) {
                    oprot.writeFieldBegin(SHOP_FIELD_DESC);
                    struct.shop.write(oprot);
                    oprot.writeFieldEnd();
                }
                oprot.writeFieldStop();
                oprot.writeStructEnd();
            }

        }

        private static class getInfos_argsTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getInfos_argsTupleScheme getScheme() {
                return new getInfos_argsTupleScheme();
            }
        }

        private static class getInfos_argsTupleScheme extends org.apache.thrift.scheme.TupleScheme<getInfos_args> {

            @Override
            public void write(org.apache.thrift.protocol.TProtocol prot, getInfos_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet optionals = new java.util.BitSet();
                if (struct.isSetShop()) {
                    optionals.set(0);
                }
                oprot.writeBitSet(optionals, 1);
                if (struct.isSetShop()) {
                    struct.shop.write(oprot);
                }
            }

            @Override
            public void read(org.apache.thrift.protocol.TProtocol prot, getInfos_args struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet incoming = iprot.readBitSet(1);
                if (incoming.get(0)) {
                    struct.shop = new Shop();
                    struct.shop.read(iprot);
                    struct.setShopIsSet(true);
                }
            }
        }
    }

    public static class getInfos_result
            implements org.apache.thrift.TBase<getInfos_result,
            getInfos_result._Fields>,
            java.io.Serializable,
            Cloneable,
            Comparable<getInfos_result> {
        // isset id assignments
        public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
        private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
                new org.apache.thrift.protocol.TStruct("getInfos_result");
        private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC =
                new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short) 0);
        private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY =
                new getInfos_resultStandardSchemeFactory();
        private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY =
                new getInfos_resultTupleSchemeFactory();

        static {
            java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap =
                    new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
            tmpMap.put(_Fields.SUCCESS,
                    new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
                    new org.apache.thrift.meta_data.ListMetaData(
                            org.apache.thrift.protocol.TType.LIST,
                            new org.apache.thrift.meta_data.StructMetaData(
                                    org.apache.thrift.protocol.TType.STRUCT, Info.class))));
            metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
            org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getInfos_result.class, metaDataMap);
        }

        public java.util.List<Info> success; // required

        public getInfos_result() {
        }

        public getInfos_result(
                java.util.List<Info> success) {
            this();
            this.success = success;
        }

        /**
         * Performs a deep copy on <i>other</i>.
         */
        public getInfos_result(getInfos_result other) {
            if (other.isSetSuccess()) {
                java.util.List<Info> __this__success = new java.util.ArrayList<Info>(other.success.size());
                for (Info other_element : other.success) {
                    __this__success.add(new Info(other_element));
                }
                this.success = __this__success;
            }
        }

        private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
            return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ?
                    STANDARD_SCHEME_FACTORY :
                    TUPLE_SCHEME_FACTORY).
                    getScheme();
        }

        public getInfos_result deepCopy() {
            return new getInfos_result(this);
        }

        @Override
        public void clear() {
            this.success = null;
        }

        public int getSuccessSize() {
            return (this.success == null) ? 0 : this.success.size();
        }

        public java.util.Iterator<Info> getSuccessIterator() {
            return (this.success == null) ? null : this.success.iterator();
        }

        public void addToSuccess(Info elem) {
            if (this.success == null) {
                this.success = new java.util.ArrayList<Info>();
            }
            this.success.add(elem);
        }

        public java.util.List<Info> getSuccess() {
            return this.success;
        }

        public getInfos_result setSuccess(java.util.List<Info> success) {
            this.success = success;
            return this;
        }

        public void unsetSuccess() {
            this.success = null;
        }

        /**
         * Returns true if field success is set (has been assigned a value) and false otherwise
         */
        public boolean isSetSuccess() {
            return this.success != null;
        }

        public void setSuccessIsSet(boolean value) {
            if (!value) {
                this.success = null;
            }
        }

        public void setFieldValue(_Fields field, java.lang.Object value) {
            switch (field) {
                case SUCCESS:
                    if (value == null) {
                        unsetSuccess();
                    } else {
                        setSuccess((java.util.List<Info>) value);
                    }
                    break;

            }
        }

        public java.lang.Object getFieldValue(_Fields field) {
            switch (field) {
                case SUCCESS:
                    return getSuccess();

            }
            throw new java.lang.IllegalStateException();
        }

        /**
         * Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise
         */
        public boolean isSet(_Fields field) {
            if (field == null) {
                throw new java.lang.IllegalArgumentException();
            }

            switch (field) {
                case SUCCESS:
                    return isSetSuccess();
            }
            throw new java.lang.IllegalStateException();
        }

        @Override
        public boolean equals(java.lang.Object that) {
            if (that == null)
                return false;
            if (that instanceof getInfos_result)
                return this.equals((getInfos_result) that);
            return false;
        }

        public boolean equals(getInfos_result that) {
            if (that == null)
                return false;
            if (this == that)
                return true;

            boolean this_present_success = true && this.isSetSuccess();
            boolean that_present_success = true && that.isSetSuccess();
            if (this_present_success || that_present_success) {
                if (!(this_present_success && that_present_success))
                    return false;
                if (!this.success.equals(that.success))
                    return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int hashCode = 1;

            hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287);
            if (isSetSuccess())
                hashCode = hashCode * 8191 + success.hashCode();

            return hashCode;
        }

        @Override
        public int compareTo(getInfos_result other) {
            if (!getClass().equals(other.getClass())) {
                return getClass().getName().compareTo(other.getClass().getName());
            }

            int lastComparison = 0;

            lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
            if (lastComparison != 0) {
                return lastComparison;
            }
            if (isSetSuccess()) {
                lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
                if (lastComparison != 0) {
                    return lastComparison;
                }
            }
            return 0;
        }

        public _Fields fieldForId(int fieldId) {
            return _Fields.findByThriftId(fieldId);
        }

        public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
            scheme(iprot).read(iprot, this);
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
            scheme(oprot).write(oprot, this);
        }

        @Override
        public java.lang.String toString() {
            java.lang.StringBuilder sb = new java.lang.StringBuilder("getInfos_result(");
            boolean first = true;

            sb.append("success:");
            if (this.success == null) {
                sb.append("null");
            } else {
                sb.append(this.success);
            }
            first = false;
            sb.append(")");
            return sb.toString();
        }

        public void validate() throws org.apache.thrift.TException {
            // check for required fields
            // check for sub-struct validity
        }

        private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
            try {
                write(
                        new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        private void readObject(java.io.ObjectInputStream in)
                throws java.io.IOException, java.lang.ClassNotFoundException {
            try {
                read(
                        new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
            } catch (org.apache.thrift.TException te) {
                throw new java.io.IOException(te);
            }
        }

        /**
         * The set of fields this struct contains, along with convenience methods for finding and manipulating them.
         */
        public enum _Fields implements org.apache.thrift.TFieldIdEnum {
            SUCCESS((short) 0, "success");

            private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();

            static {
                for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
                    byName.put(field.getFieldName(), field);
                }
            }

            private final short _thriftId;
            private final java.lang.String _fieldName;

            _Fields(short thriftId, java.lang.String fieldName) {
                _thriftId = thriftId;
                _fieldName = fieldName;
            }

            /**
             * Find the _Fields constant that matches fieldId, or null if its not found.
             */
            public static _Fields findByThriftId(int fieldId) {
                switch (fieldId) {
                    case 0: // SUCCESS
                        return SUCCESS;
                    default:
                        return null;
                }
            }

            /**
             * Find the _Fields constant that matches fieldId, throwing an exception
             * if it is not found.
             */
            public static _Fields findByThriftIdOrThrow(int fieldId) {
                _Fields fields = findByThriftId(fieldId);
                if (fields == null)
                    throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
                return fields;
            }

            /**
             * Find the _Fields constant that matches name, or null if its not found.
             */
            public static _Fields findByName(java.lang.String name) {
                return byName.get(name);
            }

            public short getThriftFieldId() {
                return _thriftId;
            }

            public java.lang.String getFieldName() {
                return _fieldName;
            }
        }

        private static class getInfos_resultStandardSchemeFactory
                implements org.apache.thrift.scheme.SchemeFactory {
            public getInfos_resultStandardScheme getScheme() {
                return new getInfos_resultStandardScheme();
            }
        }

        private static class getInfos_resultStandardScheme
                extends org.apache.thrift.scheme.StandardScheme<getInfos_result> {

            public void read(org.apache.thrift.protocol.TProtocol iprot, getInfos_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TField schemeField;
                iprot.readStructBegin();
                while (true) {
                    schemeField = iprot.readFieldBegin();
                    if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                        break;
                    }
                    switch (schemeField.id) {
                        case 0: // SUCCESS
                            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                                {
                                    org.apache.thrift.protocol.TList _list0 = iprot.readListBegin();
                                    struct.success = new java.util.ArrayList<Info>(_list0.size);
                                    Info _elem1;
                                    for (int _i2 = 0; _i2 < _list0.size; ++_i2) {
                                        _elem1 = new Info();
                                        _elem1.read(iprot);
                                        struct.success.add(_elem1);
                                    }
                                    iprot.readListEnd();
                                }
                                struct.setSuccessIsSet(true);
                            } else {
                                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                            }
                            break;
                        default:
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                    }
                    iprot.readFieldEnd();
                }
                iprot.readStructEnd();

                // check for required fields of primitive type, which can't be checked in the validate method
                struct.validate();
            }

            public void write(org.apache.thrift.protocol.TProtocol oprot, getInfos_result struct)
                    throws org.apache.thrift.TException {
                struct.validate();

                oprot.writeStructBegin(STRUCT_DESC);
                if (struct.success != null) {
                    oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
                    {
                        oprot.writeListBegin(
                                new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
                        for (Info _iter3 : struct.success) {
                            _iter3.write(oprot);
                        }
                        oprot.writeListEnd();
                    }
                    oprot.writeFieldEnd();
                }
                oprot.writeFieldStop();
                oprot.writeStructEnd();
            }

        }

        private static class getInfos_resultTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
            public getInfos_resultTupleScheme getScheme() {
                return new getInfos_resultTupleScheme();
            }
        }

        private static class getInfos_resultTupleScheme extends org.apache.thrift.scheme.TupleScheme<getInfos_result> {

            @Override
            public void write(org.apache.thrift.protocol.TProtocol prot, getInfos_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol oprot =
                        (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet optionals = new java.util.BitSet();
                if (struct.isSetSuccess()) {
                    optionals.set(0);
                }
                oprot.writeBitSet(optionals, 1);
                if (struct.isSetSuccess()) {
                    {
                        oprot.writeI32(struct.success.size());
                        for (Info _iter4 : struct.success) {
                            _iter4.write(oprot);
                        }
                    }
                }
            }

            @Override
            public void read(org.apache.thrift.protocol.TProtocol prot, getInfos_result struct)
                    throws org.apache.thrift.TException {
                org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
                java.util.BitSet incoming = iprot.readBitSet(1);
                if (incoming.get(0)) {
                    {
                        org.apache.thrift.protocol.TList _list5 =
                                new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
                        struct.success = new java.util.ArrayList<Info>(_list5.size);
                        Info _elem6;
                        for (int _i7 = 0; _i7 < _list5.size; ++_i7) {
                            _elem6 = new Info();
                            _elem6.read(iprot);
                            struct.success.add(_elem6);
                        }
                    }
                    struct.setSuccessIsSet(true);
                }
            }
        }
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/constant/Constants.java<|end_filename|>
package com.didiglobal.pressir.thrift.constant;

import java.util.regex.Pattern;

/**
 * @ClassName Constants
 * @Description
 * @Author pressir
 * @Date 2019-08-30 16:18
 */
public class Constants {

    public static final String THRIFT = "thrift://";

    public static final int URI_PARTS = 3;

    public static final String THROUGHPUT = "QPS";

    public static final String CONCURRENCY = "Concurrency";

    public static final int TIME_CONVERT_BASE = 1000;

    public static final Pattern PATTERN =
            Pattern.compile("(-*\\d+)(((s|second|seconds)?)|((m|minute|minutes)?)|((h|hour|hours)?)|((d|day|days)?)" +
                    ")");

}


<|start_filename|>src/test/java/com/pressir/idl/Shop.java<|end_filename|>
package com.pressir.idl;

/**
 * Autogenerated by Thrift Compiler (0.11.0)
 * <p>
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *
 * @generated
 */
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2019-09-05")
public class Shop implements
        org.apache.thrift.TBase<Shop, Shop._Fields>,
        java.io.Serializable,
        Cloneable,
        Comparable<Shop> {
    // isset id assignments
    public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC =
            new org.apache.thrift.protocol.TStruct("Shop");
    private static final org.apache.thrift.protocol.TField SHOP_ID_FIELD_DESC =
            new org.apache.thrift.protocol.TField("shopId", org.apache.thrift.protocol.TType.STRING, (short) 3);
    private static final org.apache.thrift.protocol.TField STATUS_FIELD_DESC =
            new org.apache.thrift.protocol.TField("status", org.apache.thrift.protocol.TType.I32, (short) 5);
    private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY =
            new ShopStandardSchemeFactory();
    private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY =
            new ShopTupleSchemeFactory();

    static {
        java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap =
                new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
        tmpMap.put(_Fields.SHOP_ID, new org.apache.thrift.meta_data.FieldMetaData("shopId",
                        org.apache.thrift.TFieldRequirementType.REQUIRED,
                new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
        tmpMap.put(_Fields.STATUS, new org.apache.thrift.meta_data.FieldMetaData("status",
                org.apache.thrift.TFieldRequirementType.REQUIRED,
                new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, ShopStatus.class)));
        metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
        org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Shop.class, metaDataMap);
    }

    public java.lang.String shopId; // required
    /**
     * @see ShopStatus
     */
    public ShopStatus status; // required

    public Shop() {
    }

    public Shop(
            java.lang.String shopId,
            ShopStatus status) {
        this();
        this.shopId = shopId;
        this.status = status;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public Shop(Shop other) {
        if (other.isSetShopId()) {
            this.shopId = other.shopId;
        }
        if (other.isSetStatus()) {
            this.status = other.status;
        }
    }

    private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
        return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ?
                STANDARD_SCHEME_FACTORY :
                TUPLE_SCHEME_FACTORY)
                .getScheme();
    }

    public Shop deepCopy() {
        return new Shop(this);
    }

    @Override
    public void clear() {
        this.shopId = null;
        this.status = null;
    }

    public java.lang.String getShopId() {
        return this.shopId;
    }

    public Shop setShopId(java.lang.String shopId) {
        this.shopId = shopId;
        return this;
    }

    public void unsetShopId() {
        this.shopId = null;
    }

    /**
     * Returns true if field shopId is set (has been assigned a value) and false otherwise
     */
    public boolean isSetShopId() {
        return this.shopId != null;
    }

    public void setShopIdIsSet(boolean value) {
        if (!value) {
            this.shopId = null;
        }
    }

    /**
     * @see ShopStatus
     */
    public ShopStatus getStatus() {
        return this.status;
    }

    /**
     * @see ShopStatus
     */
    public Shop setStatus(ShopStatus status) {
        this.status = status;
        return this;
    }

    public void unsetStatus() {
        this.status = null;
    }

    /**
     * Returns true if field status is set (has been assigned a value) and false otherwise
     */
    public boolean isSetStatus() {
        return this.status != null;
    }

    public void setStatusIsSet(boolean value) {
        if (!value) {
            this.status = null;
        }
    }

    public void setFieldValue(_Fields field, java.lang.Object value) {
        switch (field) {
            case SHOP_ID:
                if (value == null) {
                    unsetShopId();
                } else {
                    setShopId((java.lang.String) value);
                }
                break;

            case STATUS:
                if (value == null) {
                    unsetStatus();
                } else {
                    setStatus((ShopStatus) value);
                }
                break;

        }
    }

    public java.lang.Object getFieldValue(_Fields field) {
        switch (field) {
            case SHOP_ID:
                return getShopId();

            case STATUS:
                return getStatus();

        }
        throw new java.lang.IllegalStateException();
    }

    /**
     * Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise
     */
    public boolean isSet(_Fields field) {
        if (field == null) {
            throw new java.lang.IllegalArgumentException();
        }

        switch (field) {
            case SHOP_ID:
                return isSetShopId();
            case STATUS:
                return isSetStatus();
        }
        throw new java.lang.IllegalStateException();
    }

    @Override
    public boolean equals(java.lang.Object that) {
        if (that == null)
            return false;
        if (that instanceof Shop)
            return this.equals((Shop) that);
        return false;
    }

    public boolean equals(Shop that) {
        if (that == null)
            return false;
        if (this == that)
            return true;

        boolean this_present_shopId = true && this.isSetShopId();
        boolean that_present_shopId = true && that.isSetShopId();
        if (this_present_shopId || that_present_shopId) {
            if (!(this_present_shopId && that_present_shopId))
                return false;
            if (!this.shopId.equals(that.shopId))
                return false;
        }

        boolean this_present_status = true && this.isSetStatus();
        boolean that_present_status = true && that.isSetStatus();
        if (this_present_status || that_present_status) {
            if (!(this_present_status && that_present_status))
                return false;
            if (!this.status.equals(that.status))
                return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int hashCode = 1;

        hashCode = hashCode * 8191 + ((isSetShopId()) ? 131071 : 524287);
        if (isSetShopId())
            hashCode = hashCode * 8191 + shopId.hashCode();

        hashCode = hashCode * 8191 + ((isSetStatus()) ? 131071 : 524287);
        if (isSetStatus())
            hashCode = hashCode * 8191 + status.getValue();

        return hashCode;
    }

    @Override
    public int compareTo(Shop other) {
        if (!getClass().equals(other.getClass())) {
            return getClass().getName().compareTo(other.getClass().getName());
        }

        int lastComparison = 0;

        lastComparison = java.lang.Boolean.valueOf(isSetShopId()).compareTo(other.isSetShopId());
        if (lastComparison != 0) {
            return lastComparison;
        }
        if (isSetShopId()) {
            lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.shopId, other.shopId);
            if (lastComparison != 0) {
                return lastComparison;
            }
        }
        lastComparison = java.lang.Boolean.valueOf(isSetStatus()).compareTo(other.isSetStatus());
        if (lastComparison != 0) {
            return lastComparison;
        }
        if (isSetStatus()) {
            lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.status, other.status);
            if (lastComparison != 0) {
                return lastComparison;
            }
        }
        return 0;
    }

    public _Fields fieldForId(int fieldId) {
        return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
        scheme(iprot).read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
        scheme(oprot).write(oprot, this);
    }

    @Override
    public java.lang.String toString() {
        java.lang.StringBuilder sb = new java.lang.StringBuilder("Shop(");
        boolean first = true;

        sb.append("shopId:");
        if (this.shopId == null) {
            sb.append("null");
        } else {
            sb.append(this.shopId);
        }
        first = false;
        if (!first) sb.append(", ");
        sb.append("status:");
        if (this.status == null) {
            sb.append("null");
        } else {
            sb.append(this.status);
        }
        first = false;
        sb.append(")");
        return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
        // check for required fields
        if (shopId == null) {
            throw new org.apache.thrift.protocol.TProtocolException(
                    "Required field 'shopId' was not present! Struct: " + toString());
        }
        if (status == null) {
            throw new org.apache.thrift.protocol.TProtocolException(
                    "Required field 'status' was not present! Struct: " + toString());
        }
        // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
        try {
            write(new org.apache.thrift.protocol.TCompactProtocol(
                    new org.apache.thrift.transport.TIOStreamTransport(out)));
        } catch (org.apache.thrift.TException te) {
            throw new java.io.IOException(te);
        }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
        try {
            read(new org.apache.thrift.protocol.TCompactProtocol(
                    new org.apache.thrift.transport.TIOStreamTransport(in)));
        } catch (org.apache.thrift.TException te) {
            throw new java.io.IOException(te);
        }
    }

    /**
     * The set of fields this struct contains, along with convenience methods for finding and manipulating them.
     */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
        SHOP_ID((short) 3, "shopId"),
        /**
         * @see ShopStatus
         */
        STATUS((short) 5, "status");

        private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();

        static {
            for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
                byName.put(field.getFieldName(), field);
            }
        }

        private final short _thriftId;
        private final java.lang.String _fieldName;

        _Fields(short thriftId, java.lang.String fieldName) {
            _thriftId = thriftId;
            _fieldName = fieldName;
        }

        /**
         * Find the _Fields constant that matches fieldId, or null if its not found.
         */
        public static _Fields findByThriftId(int fieldId) {
            switch (fieldId) {
                case 3: // SHOP_ID
                    return SHOP_ID;
                case 5: // STATUS
                    return STATUS;
                default:
                    return null;
            }
        }

        /**
         * Find the _Fields constant that matches fieldId, throwing an exception
         * if it is not found.
         */
        public static _Fields findByThriftIdOrThrow(int fieldId) {
            _Fields fields = findByThriftId(fieldId);
            if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
            return fields;
        }

        /**
         * Find the _Fields constant that matches name, or null if its not found.
         */
        public static _Fields findByName(java.lang.String name) {
            return byName.get(name);
        }

        public short getThriftFieldId() {
            return _thriftId;
        }

        public java.lang.String getFieldName() {
            return _fieldName;
        }
    }

    private static class ShopStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
        public ShopStandardScheme getScheme() {
            return new ShopStandardScheme();
        }
    }

    private static class ShopStandardScheme extends org.apache.thrift.scheme.StandardScheme<Shop> {

        public void read(org.apache.thrift.protocol.TProtocol iprot, Shop struct) throws org.apache.thrift.TException {
            org.apache.thrift.protocol.TField schemeField;
            iprot.readStructBegin();
            while (true) {
                schemeField = iprot.readFieldBegin();
                if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                    break;
                }
                switch (schemeField.id) {
                    case 3: // SHOP_ID
                        if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                            struct.shopId = iprot.readString();
                            struct.setShopIdIsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 5: // STATUS
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.status = ShopStatus.findByValue(iprot.readI32());
                            struct.setStatusIsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    default:
                        org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                }
                iprot.readFieldEnd();
            }
            iprot.readStructEnd();

            // check for required fields of primitive type, which can't be checked in the validate method
            struct.validate();
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot, Shop struct) throws org.apache.thrift.TException {
            struct.validate();

            oprot.writeStructBegin(STRUCT_DESC);
            if (struct.shopId != null) {
                oprot.writeFieldBegin(SHOP_ID_FIELD_DESC);
                oprot.writeString(struct.shopId);
                oprot.writeFieldEnd();
            }
            if (struct.status != null) {
                oprot.writeFieldBegin(STATUS_FIELD_DESC);
                oprot.writeI32(struct.status.getValue());
                oprot.writeFieldEnd();
            }
            oprot.writeFieldStop();
            oprot.writeStructEnd();
        }

    }

    private static class ShopTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
        public ShopTupleScheme getScheme() {
            return new ShopTupleScheme();
        }
    }

    private static class ShopTupleScheme extends org.apache.thrift.scheme.TupleScheme<Shop> {

        @Override
        public void write(org.apache.thrift.protocol.TProtocol prot, Shop struct) throws org.apache.thrift.TException {
            org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
            oprot.writeString(struct.shopId);
            oprot.writeI32(struct.status.getValue());
        }

        @Override
        public void read(org.apache.thrift.protocol.TProtocol prot, Shop struct) throws org.apache.thrift.TException {
            org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
            struct.shopId = iprot.readString();
            struct.setShopIdIsSet(true);
            struct.status = ShopStatus.findByValue(iprot.readI32());
            struct.setStatusIsSet(true);
        }
    }
}



<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/generator/InvariantTaskGenerator.java<|end_filename|>
package com.didiglobal.pressir.thrift.generator;

import com.didiglobal.pressir.thrift.base.ServiceClientInvocation;
import org.apache.thrift.TServiceClient;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName InvariantTaskGenerator
 * @Description 固参任务生成器
 * @Author pressir
 * @Date 2019-09-03 09:49
 */
public class InvariantTaskGenerator<T extends TServiceClient> implements Generator {

    private final ServiceClientInvocation<T> invocation;
    private final Method method;
    private final Object[] args;

    public InvariantTaskGenerator(ServiceClientInvocation<T> invocation, Method method, Object[] args) {
        this.invocation = invocation;
        this.method = method;
        this.args = args;
    }

    @Override
    public List<Runnable> generate(int num) {
        List<Runnable> tasks = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            tasks.add(this::execute);
        }
        return tasks;
    }

    private void execute() {
        this.invocation.invoke(this.method, this.args);
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/load/Pressure.java<|end_filename|>
package com.didiglobal.pressir.thrift.load;

import com.didiglobal.pressir.thrift.constant.Constants;

/**
 * @ClassName Pressure
 * @Description 压力曲线
 * @Author pressir
 * @Date 2019-08-30 16:34
 */
public class Pressure {

    private int quantity;

    private int duration;

    private long beginTime;

    public Pressure(int quantity, String duration) {
        this(quantity, duration, System.currentTimeMillis() / Constants.TIME_CONVERT_BASE + 1);
    }

    private Pressure(int quantity, String duration, long beginTime) {
        if (quantity <= 0) {
            throw new IllegalArgumentException("the pressure should be greater than 0");
        }
        this.quantity = quantity;
        this.duration = DurationParser.parse(duration);
        if (this.duration <= 0) {
            throw new IllegalArgumentException("the duration should be greater than 0");
        }
        this.beginTime = beginTime;
    }

    public int getCurrentQuantity() {
        if (System.currentTimeMillis() / Constants.TIME_CONVERT_BASE - this.beginTime >= this.duration) {
            return -1;
        }
        return this.quantity;
    }

}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/base/transport/TSocketFactoryTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.base.transport;

import com.didiglobal.pressir.thrift.context.ContextParser;
import org.junit.Assert;
import org.junit.Test;


public class TSocketFactoryTest {

    @Test
    public void shouldReturnTSocketFactoryDefault() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TSocket");
        Assert.assertTrue(factory instanceof TSocketFactory);
    }

    @Test
    public void shouldReturnTSocketFactoryWithTimeoutSet() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TSocket(timeout=1)");
        Assert.assertTrue(factory instanceof TSocketFactory);
    }

    @Test
    public void shouldReturnTSocketFactoryWithAllTimeoutSet() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TSocket(socketTimeout=1, connectTimeout=1)");
        Assert.assertTrue(factory instanceof TSocketFactory);
    }

}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/load/DurationParserTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.load;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class DurationParserTest {

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowException() {
        DurationParser.parse("s");
    }

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionWhenGivenErrorFormat() {
        DurationParser.parse("abc10s");
    }

    @Test
    public void shouldReturn9() {
        Assert.assertEquals(9, DurationParser.parse("9"));
    }

    @Test
    public void shouldReturn10() {
        Assert.assertEquals(10, DurationParser.parse("10s"));
    }

    @Test
    public void shouldReturn11() {
        Assert.assertEquals(11, DurationParser.parse("11second"));
    }

    @Test
    public void shouldReturn12() {
        Assert.assertEquals(12, DurationParser.parse("12seconds"));
    }

    @Test
    public void shouldReturn60() {
        Assert.assertEquals(60, DurationParser.parse("1m"));
    }

    @Test
    public void shouldReturn120() {
        Assert.assertEquals(120, DurationParser.parse("2minute"));
    }

    @Test
    public void shouldReturn180() {
        Assert.assertEquals(180, DurationParser.parse("3minutes"));
    }

    @Test
    public void shouldReturn3600() {
        Assert.assertEquals(3600, DurationParser.parse("1h"));
    }

    @Test
    public void shouldReturn7200() {
        Assert.assertEquals(7200, DurationParser.parse("2hour"));
    }

    @Test
    public void shouldReturn10800() {
        Assert.assertEquals(10800, DurationParser.parse("3hours"));
    }

    @Test
    public void shouldReturn10800Multi24() {
        Assert.assertEquals(3600 * 24, DurationParser.parse("1d"));
    }

    @Test
    public void shouldReturn10800Multi48() {
        Assert.assertEquals(3600 * 48, DurationParser.parse("2day"));
    }

    @Test
    public void shouldReturn10800Multi72() {
        Assert.assertEquals(3600 * 72, DurationParser.parse("3days"));
    }

    /**
     * perf test
     */
    @Test
    public void perfShouldParse1mWithin3Seconds() {
        long start = System.currentTimeMillis();
        int count = 1000000;
        for (int i = 0; i < count; i++) {
            DurationParser.parse(i + "hours");
        }
        long timeSpent = System.currentTimeMillis() - start;
        assertTrue("expects <3000ms, actual is " + timeSpent + "ms", timeSpent < 3000);
    }
}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/MainTest.java<|end_filename|>
package com.didiglobal.pressir.thrift;

import com.pressir.idl.service.Service;
import org.apache.thrift.transport.TTransportException;
import org.junit.Before;

import java.util.Objects;


public class MainTest {

    private String path = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
    private String thriftConf = path + "thrift.conf";
    private String paramConf = path + "data.text";

    @Before
    public void before() {
        new Thread(() -> {
            try {
                Service.run();
            } catch (TTransportException e) {
                e.printStackTrace();
            }
        }).start();
    }

    @org.junit.Test
    public void shouldRunningWhenGivenRightParamsOnThroughput() {
        Main.main("-q", "100", "-t", "20s", "-e", thriftConf, "-u", "127.0.0.1:8090/Soda/getInfos?@"+paramConf);
    }

//    @org.junit.Test
//    public void shouldRunningWhenGivenRightParamsOnConcurrency() {
//        Main.main("-c", "2", "-t", "20s", "-e", thriftConf, "-u", "127.0.0.1:8090/Soda/getInfos?@"+paramConf);
//    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/generator/Generator.java<|end_filename|>
package com.didiglobal.pressir.thrift.generator;

import java.util.List;

/**
 * @InterfaceName Generator
 * @Description 任务生成器
 * @Author pressir
 * @Date 2019-09-03 09:50
 */
public interface Generator {
    /**
     * 根据输入的数字生成相应数量的Runnable
     * @param num a num of tasks
     * @return a runnable list
     */
    List<Runnable> generate(int num);
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/Main.java<|end_filename|>
package com.didiglobal.pressir.thrift;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.converters.FileConverter;
import com.didiglobal.pressir.thrift.console.ConsolePrinter;
import com.didiglobal.pressir.thrift.constant.Constants;
import com.didiglobal.pressir.thrift.context.InvocationContext;
import com.didiglobal.pressir.thrift.executor.PressureExecutor;
import com.didiglobal.pressir.thrift.generator.Generator;
import com.didiglobal.pressir.thrift.load.DurationParser;
import com.didiglobal.pressir.thrift.load.Pressure;
import com.didiglobal.pressir.thrift.monitor.Monitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.concurrent.TimeUnit;


/**
 * @ClassName Main
 * @Description main
 * @Author pressir
 * @Date 2019-08-30 15:57
 */
public class Main {

    private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

    @Parameter(names = {"-c"}, description = "concurrency")
    private Integer threadNum;

    @Parameter(names = {"-t"}, description = "timeLimit", required = true)
    private String timeLimit;

    @Parameter(names = {"-q"}, description = "throughput")
    private Integer throughput;

    @Parameter(names = {"-e"}, description = "thrift env", required = true, converter = FileConverter.class)
    private File thriftEnv;

    @Parameter(names = {"-u"}, description = "url", required = true)
    private String url;

    public static void main(String... args) {
        Main main = new Main();
        try {
            JCommander.newBuilder().addObject(main).build().parse(args);
        } catch (ParameterException e) {
            ConsolePrinter.onError(e.getMessage());
            ConsolePrinter.printUsage();
            return;
        }
        try {
            main.run();
            TimeUnit.SECONDS.sleep(5);
            Monitor.onStop();
            ConsolePrinter.sayGoodbye();
        } catch (Exception e) {
            ConsolePrinter.onError(e.getMessage());
        }
    }

    private void run() {

        InvocationContext invocationContext = new InvocationContext(this.thriftEnv, this.url);

        //prepare executor
        try (PressureExecutor pressureExecutor = this.getExecutor(invocationContext.getTaskGenerator())) {
            //prepare monitor
            Monitor.init(invocationContext.getMethod(), DurationParser.parse(this.timeLimit) / 10);
            ConsolePrinter.say("Server Hostname: {}", invocationContext.getEndpoint().getHost());
            ConsolePrinter.say("Server Port: {}", invocationContext.getEndpoint().getPort());
            ConsolePrinter.say("Thrift Service: {}", invocationContext.getService());
            ConsolePrinter.say("Thrift Method: {}", invocationContext.getMethod());
            ConsolePrinter.say("Type: {}", this.threadNum == null ?
                    this.throughput + " " + Constants.THROUGHPUT :
                    this.threadNum + " " + Constants.CONCURRENCY);
            ConsolePrinter.say("Duration: {}", this.timeLimit);
            ConsolePrinter.say("Benchmarking {}/{}/{}",
                    invocationContext.getEndpoint(),
                    invocationContext.getService(),
                    invocationContext.getMethod());
            pressureExecutor.start(1);
        }
    }

    private PressureExecutor getExecutor(Generator generator) {
        if (this.threadNum != null) {
            Pressure pressure = new Pressure(this.threadNum, this.timeLimit);
            return PressureExecutor.concurrency(generator, pressure::getCurrentQuantity);
        }

        Pressure pressure = new Pressure(this.throughput, this.timeLimit);
        return PressureExecutor.throughput(generator, pressure::getCurrentQuantity);
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/context/InvocationContext.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;

import com.didiglobal.pressir.thrift.base.ServiceClientInvocation;
import com.didiglobal.pressir.thrift.base.transport.TTransportFactory;
import com.didiglobal.pressir.thrift.generator.Generator;
import com.didiglobal.pressir.thrift.generator.InvariantTaskGenerator;
import com.didiglobal.pressir.thrift.utils.ReflectUtils;
import com.google.common.io.Files;
import com.google.common.net.HostAndPort;
import org.apache.logging.log4j.util.Strings;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.TServiceClientFactory;
import org.apache.thrift.protocol.TProtocolFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import static com.didiglobal.pressir.thrift.constant.Constants.THRIFT;

/**
 * @ClassName InvocationContext
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:09
 */
public class InvocationContext {

    private static final String MARK_PATH = "?";

    private static final char MARK_FILE = '@';

    private HostAndPort endpoint;

    private String service;

    private String method;

    private List<String> arguments;

    private CustomClassLoader classLoader;

    private TProtocolFactory protocolFactory;

    private TTransportFactory transportFactory;

    public InvocationContext(File thriftEnv, String uri) {
        this.parseURI(uri);
        this.readThriftEnv(thriftEnv);
    }

    private static Object[] castArgs(Method method, String[] args) {
        try {
            return ReflectUtils.castArgs(method, args);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static TServiceClientFactory genServiceClientClass(Class<? extends TServiceClient> serviceClientClass) {
        try {
            return (TServiceClientFactory) ReflectUtils.findInnerClass(serviceClientClass, "Factory").newInstance();
        } catch (Exception e) {
            throw new IllegalStateException("serviceClient(" + serviceClientClass.getName() + ") is invalid", e);
        }
    }

    private void parseURI(String uri) {
        uri = uri.substring(THRIFT.length());
        int index = uri.indexOf("/");
        this.endpoint = HostAndPort.fromString(uri.substring(0, index));
        uri = uri.substring(index + 1);
        index = uri.indexOf("/");
        this.service = uri.substring(0, index);
        getMethodAndArgs(uri.substring(index + 1));
    }

    private void getMethodAndArgs(String shard) {
        if (shard.contains(MARK_PATH)) {
            int index = shard.indexOf(MARK_PATH);
            this.method = shard.substring(0, index);
            if (shard.length() > index + 1) {
                char c = shard.charAt(index + 1);
                if (c == MARK_FILE) {
                    readArgsData(new File(shard.substring(index + 2)));
                } else {
                    convertArgs(shard.substring(index + 1));
                }
            } else {
                readArgsData(null);
            }
        } else {
            this.method = shard;
            readArgsData(null);
        }
    }

    private void readThriftEnv(File thriftEnv) {
        Properties properties = new Properties();
        try (FileInputStream fis = new FileInputStream(thriftEnv)) {
            properties.load(fis);
        } catch (IOException e) {
            throw new IllegalStateException("load thrift environment file error cause by " + e.getMessage(), e);
        }
        String clientJar = properties.getProperty("client_jar");
        File jarFile = (clientJar.charAt(0) == File.separatorChar) ?
                new File(clientJar) :
                new File(thriftEnv.getParent(), clientJar);
        try {
            this.classLoader = new CustomClassLoader(jarFile);
        } catch (IOException e) {
            throw new IllegalStateException("client_jar(" + jarFile + ") in thrift environment file is invalid", e);
        }

        String protocol = properties.getProperty("protocol");
        try {
            this.protocolFactory = ContextParser.parseProtocolFactory(protocol);
        } catch (Exception e) {
            throw new IllegalStateException("protocol(" + protocol + ") in thrift environment file is invalid", e);
        }
        if (this.protocolFactory == null) {
            throw new IllegalStateException("protocol(" + protocol + ") in thrift environment file is invalid" + protocol);
        }

        String transport = properties.getProperty("transport");
        try {
            this.transportFactory = ContextParser.parseTransportFactory(transport);
        } catch (Exception e) {
            throw new IllegalStateException("transport(" + transport + ") in thrift environment file is invalid", e);
        }
        if (this.transportFactory == null) {
            throw new IllegalStateException("transport(" + transport + ") in thrift environment file is invalid");
        }
    }

    private void convertArgs(String argsString) {
        if (Strings.isBlank(argsString)) {
            this.arguments = null;
            return;
        }
        this.arguments = Arrays.asList(argsString.split("&"));
    }

    private void readArgsData(File argsData) {
        if (argsData == null) {
            this.arguments = null;
            return;
        }
        if (!argsData.exists()) {
            throw new IllegalStateException("data file(" + argsData.getPath() + ") is missing");
        }
        if (!argsData.isFile()) {
            throw new IllegalStateException(argsData.getPath() + " isn't a file");
        }
        try {
            this.arguments = Files.readLines(argsData, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new IllegalStateException("args(" + argsData.getPath() + ") is invalid", e);
        }
    }

    public HostAndPort getEndpoint() {
        return endpoint;
    }

    public String getService() {
        return service;
    }

    public String getMethod() {
        return method;
    }

    public <T extends TServiceClient> Generator getTaskGenerator() {
        Class<? extends TServiceClient> serviceClientClass;
        Method method;
        try {
            serviceClientClass =
                    (Class<? extends TServiceClient>) this.classLoader.loadClass(this.service.concat("$Client"));
            method = ReflectUtils.findMethod(serviceClientClass, this.method);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException("specified service(" + this.service + ") is invalid", e);
        } catch (NoSuchMethodException e) {
            throw new IllegalStateException("specified method(" + this.method + ") is invalid", e);
        }
        TServiceClientFactory<T> serviceClientFactory = genServiceClientClass(serviceClientClass);
        ServiceClientInvocation<T> invocation = new ServiceClientInvocation<>(
                serviceClientFactory,
                this.protocolFactory,
                this.transportFactory,
                this.endpoint);
        Object[] args = castArgs(method, this.arguments == null ? null : this.arguments.toArray(new String[0]));
        return new InvariantTaskGenerator<>(invocation, method, args);
    }

}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/utils/ReflectUtilsTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.utils;


import com.alibaba.fastjson.JSON;
import com.pressir.idl.Shop;
import com.pressir.idl.ShopStatus;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class ReflectUtilsTest {
    private static Shop shop = new Shop("shop", ShopStatus.OPEN);
    private static List<Shop> aList = Arrays.asList(shop);
    private static Set<Shop> aSet = new HashSet<>(Arrays.asList(shop));
    private static Map<Integer, Shop> aMap = Collections.singletonMap(7, shop);
    private final ThreadLocal<Type> paramType = new ThreadLocal<Type>();
    private Object paramValue;
    private String stringValue;

    public ReflectUtilsTest(Type paramType, Object paramValue, String stringValue) {
        this.paramType.set(paramType);
        this.paramValue = paramValue;
        this.stringValue = stringValue;
    }

    @Parameterized.Parameters
    public static Collection paramTypeValues() {
        return Arrays.asList(new Object[][]{
                {byte.class, (byte) 1, Byte.toString((byte) 1)},
                {boolean.class, true, "true"},
                {short.class, (short) 2, Short.toString((short) 2)},
                {char.class, 'c', String.valueOf('c')},
                {int.class, 3, String.valueOf(3)},
                {long.class, (long) 4, String.valueOf(4)},
                {float.class, (float) 5.0, String.valueOf(5.0)},
                {double.class, 6.0, String.valueOf(6.0)},
                {String.class, "string", "string"},
                {getGenericTypeOf("shop"), shop, "" + JSON.toJSONString(shop)},
                {getGenericTypeOf("aList"), aList, "" + JSON.toJSONString(aList)},
                {getGenericTypeOf("aSet"), aSet, "" + JSON.toJSONString(aSet)},
                {getGenericTypeOf("aMap"), aMap, JSON.toJSONString(aMap)},
                {BigDecimal.class, new BigDecimal(13), JSON.toJSONString(new BigDecimal(13))},
                {BigInteger.class, new BigInteger("14"), JSON.toJSONString(new BigInteger("14"))},
        });
    }

    private static Type getGenericTypeOf(String fieldName) {
        try {
            Type genericType = ReflectUtilsTest.class.getDeclaredField(fieldName).getGenericType();
            return genericType;
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Test
    public void testPrimeNumberChecker() {
        System.out.println("Parameterized value is : " + stringValue);
        assertEquals(paramValue, ReflectUtils.cast(stringValue, paramType.get()));
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/base/transport/TSocketFactory.java<|end_filename|>
package com.didiglobal.pressir.thrift.base.transport;

import com.google.common.net.HostAndPort;
import org.apache.thrift.transport.TSocket;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Map;

/**
 * @ClassName TSocketFactory
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:13
 */
public class TSocketFactory implements TTransportFactory<TSocket> {

    private final int[] timeouts;

    private final Constructor<TSocket> constructor;

    public TSocketFactory(Map<String, String> attrs) {
        this.timeouts = parseTimeout(attrs);
        Class<?>[] parameterTypes = new Class<?>[this.timeouts.length + 2];
        parameterTypes[0] = String.class;
        parameterTypes[1] = int.class;
        for (int i = 0; i < this.timeouts.length; i++) {
            parameterTypes[2 + i] = int.class;
        }
        try {
            this.constructor = TSocket.class.getConstructor(parameterTypes);
        } catch (NoSuchMethodException e) {
            throw new IllegalStateException("Invalid construct method TSocket(" + Arrays.toString(parameterTypes) + ")");
        }
    }

    @Override
    public TSocket getTransport(HostAndPort endpoint) {
        Object[] initargs = new Object[this.timeouts.length + 2];
        initargs[0] = endpoint.getHost();
        initargs[1] = endpoint.getPort();
        for (int i = 0; i < this.timeouts.length; i++) {
            initargs[2 + i] = this.timeouts[i];
        }
        try {
            return this.constructor.newInstance(initargs);
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new IllegalStateException(e);
        }
    }

    private static int[] parseTimeout(Map<String, String> attrs) {
        String socketTimeoutAttr = attrs.get("socketTimeout");
        if (socketTimeoutAttr == null) {
            String connectTimeoutAttr = attrs.get("connectTimeout");
            if (connectTimeoutAttr != null) {
                int socketTimeout = toInt(attrs.get("timeout"), 0);
                int connectTimeout = Integer.parseInt(connectTimeoutAttr);
                return new int[]{socketTimeout, connectTimeout};
            }
            String timeoutAttr = attrs.get("timeout");
            if (timeoutAttr == null) {
                return new int[0];
            }
            int timeout = Integer.parseInt(timeoutAttr);
            return new int[]{timeout};
        } else {
            int socketTimeout = Integer.parseInt(socketTimeoutAttr);
            int connectTimeout;
            String connectTimeoutAttr = attrs.get("connectTimeout");
            if (connectTimeoutAttr != null) {
                connectTimeout = Integer.parseInt(connectTimeoutAttr);
            } else {
                connectTimeout = toInt(attrs.get("timeout"), 0);
            }
            return new int[]{socketTimeout, connectTimeout};
        }
    }

    private static int toInt(String s, int defaultValue) {
        if (s == null) {
            return defaultValue;
        } else {
            return Integer.parseInt(s);
        }
    }
}



<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/console/ConsolePrinter.java<|end_filename|>
package com.didiglobal.pressir.thrift.console;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Only logs in this file could be printed in console.
 */

/**
 * @author zhangxiaoqing
 */
public class ConsolePrinter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ConsolePrinter.class);
    private static String name = "BenchmarkThrift";
    private static String shell = "benchmark";

    public static void sayGoodbye() {
        say("Thank you for using {}, Bye!", name);
    }

    public static void say(String msg, Object... vars) {
        LOGGER.info(msg, vars);
    }

    public static void onError(String message, Object... vars) {
        LOGGER.error("{}: " + message, shell, vars);
    }

    public static void printUsage() {
        say("{}: use -h for usages", shell);
    }
}


<|start_filename|>src/test/java/com/didiglobal/pressir/thrift/context/ContextParserTest.java<|end_filename|>
package com.didiglobal.pressir.thrift.context;


import com.didiglobal.pressir.thrift.base.transport.TFramedTransportFactory;
import com.didiglobal.pressir.thrift.base.transport.TSocketFactory;
import com.didiglobal.pressir.thrift.base.transport.TTransportFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.protocol.TSimpleJSONProtocol;
import org.apache.thrift.protocol.TTupleProtocol;
import org.junit.Assert;
import org.junit.Test;

public class ContextParserTest {
    @Test
    public void shouldReturnTSocketFactory() {
        TTransportFactory factory = ContextParser.parseTransportFactory("TSocket(socketTimeout=1, connectTimeout=1)");
        Assert.assertTrue(factory instanceof TSocketFactory);
    }

    @Test
    public void shouldReturnTFramedTransportFactory() {
        TTransportFactory factory = ContextParser.parseTransportFactory(
                "TFramedTransport(transport=TSocket(timeout=1), maxLength=100)");
        Assert.assertTrue(factory instanceof TFramedTransportFactory);
    }

    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionWhenSetErrorTTransport() {
        ContextParser.parseTransportFactory("TxxxTransport");
    }

    @Test
    public void shouldReturnTBinaryProtocolFactory() {
        TProtocolFactory factory = ContextParser.parseProtocolFactory("TBinaryProtocol");
        Assert.assertTrue(factory instanceof TBinaryProtocol.Factory);
    }

    @Test
    public void shouldReturnTCompactProtocolFactory() {
        TProtocolFactory factory = ContextParser.parseProtocolFactory("TCompactProtocol");
        Assert.assertTrue(factory instanceof TCompactProtocol.Factory);
    }

    @Test
    public void shouldReturnTTupleProtocolFactory() {
        TProtocolFactory factory = ContextParser.parseProtocolFactory("TTupleProtocol");
        Assert.assertTrue(factory instanceof TTupleProtocol.Factory);
    }

    @Test
    public void shouldReturnTJSONProtocolFactory() {
        TProtocolFactory factory = ContextParser.parseProtocolFactory("TJSONProtocol");
        Assert.assertTrue(factory instanceof TJSONProtocol.Factory);
    }

    @Test
    public void shouldReturnTSimpleJSONProtocolFactory() {
        TProtocolFactory factory = ContextParser.parseProtocolFactory("TSimpleJSONProtocol");
        Assert.assertTrue(factory instanceof TSimpleJSONProtocol.Factory);
    }



    @Test(expected = IllegalArgumentException.class)
    public void shouldThrowExceptionWhenSetErrorTProtocol() {
        ContextParser.parseProtocolFactory("TxxxProtocol");
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/base/transport/TFramedTransportFactory.java<|end_filename|>
package com.didiglobal.pressir.thrift.base.transport;

import com.google.common.net.HostAndPort;
import com.didiglobal.pressir.thrift.context.ContextParser;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TTransport;

import java.util.Collections;
import java.util.Map;

/**
 * @ClassName TFramedTransportFactory
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:15
 */
public class TFramedTransportFactory implements TTransportFactory<TFramedTransport> {
    private final TTransportFactory transportFactory;

    private final TFramedTransport.Factory framedTransportFactory;

    public TFramedTransportFactory(Map<String, String> attrs) {
        String transportAttr = attrs.get("transport");
        //TSocketFactory for default
        if (transportAttr == null) {
            this.transportFactory = new TSocketFactory(Collections.emptyMap());
        } else {
            this.transportFactory = ContextParser.parseTransportFactory(transportAttr);
        }
        this.framedTransportFactory = new TFramedTransport.Factory();
        ContextParser.setField(this.framedTransportFactory, attrs);
    }

    @Override
    public TFramedTransport getTransport(HostAndPort endpoint) {
        TTransport transport = this.transportFactory.getTransport(endpoint);
        return (TFramedTransport) this.framedTransportFactory.getTransport(transport);
    }

}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/base/ServiceClientInvocation.java<|end_filename|>
package com.didiglobal.pressir.thrift.base;

import com.didiglobal.pressir.thrift.base.transport.TTransportFactory;
import com.didiglobal.pressir.thrift.monitor.Monitor;
import com.google.common.net.HostAndPort;
import org.apache.thrift.TBase;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.TServiceClientFactory;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @ClassName ServiceClientInvocation
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:09
 */
public class ServiceClientInvocation<T extends TServiceClient> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceClientInvocation.class);

    private final TServiceClientFactory<T> serviceClientFactory;

    private final TProtocolFactory protocolFactory;

    private final TTransportFactory transportFactory;

    private final HostAndPort endpoint;

    public ServiceClientInvocation(
            TServiceClientFactory<T> serviceClientFactory,
            TProtocolFactory protocolFactory,
            TTransportFactory transportFactory,
            HostAndPort endpoint) {
        this.serviceClientFactory = Objects.requireNonNull(serviceClientFactory);
        this.protocolFactory = Objects.requireNonNull(protocolFactory);
        this.transportFactory = Objects.requireNonNull(transportFactory);
        this.endpoint = Objects.requireNonNull(endpoint);
    }

    public void invoke(Method method, Object... args) {
        String keyword = method.getName();
        T client = this.getClient();
        long startAt = System.currentTimeMillis();
        try {
            Monitor.onConnect(keyword);
            this.open(client);
            Monitor.onSend(keyword);
            Object o = method.invoke(client, args);
            Monitor.onReceived(keyword, (int) (System.currentTimeMillis() - startAt));
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Received: {}", method.getReturnType().cast(o));
            }
        } catch (Exception e) {
            if (e instanceof TBase) {
                Monitor.onReceived(keyword, (int) (System.currentTimeMillis() - startAt));
            } else {
                Monitor.onError(keyword, e);
            }
        } finally {
            this.close(client);
        }
    }

    private T getClient() {
        TTransport transport = this.transportFactory.getTransport(this.endpoint);
        TProtocol protocol = this.protocolFactory.getProtocol(transport);
        return this.serviceClientFactory.getClient(protocol);
    }

    private void open(T client) throws TTransportException {
        TProtocol iprot = client.getInputProtocol();
        TTransport itrans = iprot.getTransport();
        if (!itrans.isOpen()) {
            itrans.open();
        }
        TProtocol oprot = client.getOutputProtocol();
        if (oprot == iprot) {
            return;
        }
        TTransport otrans = oprot.getTransport();
        if (otrans == itrans) {
            return;
        }
        if (!otrans.isOpen()) {
            otrans.open();
        }
    }

    private void close(T client) {
        TProtocol iprot = client.getInputProtocol();
        TProtocol oprot = client.getOutputProtocol();
        if (oprot == iprot) {
            iprot.getTransport().close();
            return;
        }
        TTransport itrans = iprot.getTransport();
        TTransport otrans = oprot.getTransport();
        if (otrans == itrans) {
            itrans.close();
            return;
        }
        try {
            itrans.close();
            otrans.close();
        } finally {
            otrans.close();
        }
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/monitor/Monitor.java<|end_filename|>
package com.didiglobal.pressir.thrift.monitor;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName Monitor
 * @Description 监控
 * @Author pressir
 * @Date 2019-08-30 17:25
 */
public class Monitor {
    private static Map<String, Statistic> map = new ConcurrentHashMap<>();

    public static void init(String keyword, int interval) {
        if (map.get(keyword) == null) {
            map.put(keyword, new Statistic(interval));
        }
    }

    public static void onSend(String keyword) {
        map.get(keyword).onSend();
    }

    public static void onError(String keyword, Exception e) {
        map.get(keyword).onError(e);
    }

    public static void onReceived(String keyword, int timeSpent) {
        map.get(keyword).onReceived(timeSpent);
    }

    public static void onStop() {
        map.values().forEach(Statistic::onStop);
    }

    public static void onConnect(String keyword) {
        map.get(keyword).onConnect();
    }
}


<|start_filename|>src/main/java/com/didiglobal/pressir/thrift/base/transport/TTransportFactory.java<|end_filename|>
package com.didiglobal.pressir.thrift.base.transport;

import com.google.common.net.HostAndPort;
import org.apache.thrift.transport.TTransport;

/**
 * @InterfaceName TTransportFactory
 * @Description TODO
 * @Author pressir
 * @Date 2019-09-19 21:14
 */
public interface TTransportFactory<T extends TTransport> {
    T getTransport(HostAndPort endpoint);
}
