Package com.guokr.simbase.server

Source Code of com.guokr.simbase.server.ServerHandler

package com.guokr.simbase.server;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.guokr.simbase.SimCallback;
import com.guokr.simbase.SimCommand;
import com.guokr.simbase.SimEngine;
import com.guokr.simbase.SimRegistry;
import com.guokr.simbase.SimRequest;
import com.guokr.simbase.SimUtils;
import com.guokr.simbase.util.PrefixThreadFactory;

public class ServerHandler implements IHandler {
    private final ExecutorService execs;
    private final SimRegistry     registry;
    private final SimEngine       engine;

    public ServerHandler(int threadPoolSize, String prefix, int queueSize, SimRegistry registry, SimEngine engine) {
        this.registry = registry;
        this.engine = engine;
        PrefixThreadFactory factory = new PrefixThreadFactory(prefix);
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(queueSize);
        this.execs = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.MILLISECONDS, queue, factory);
    }

    public void handle(final RedisRequests reqs, final RespCallback cb) {
        execs.submit(new Runnable() {
            @Override
            public void run() {
                int order = 0;
                ServerCallback root = new ServerCallback(reqs.length(), cb);
                for (final SimRequest request : reqs) {
                    SimCallback callback = new PipedCallback(order++, root);
                    try {
                        SimCommand command = registry.get(request.name());
                        String sig = command.signature();
                        switch (sig.length()) {
                        case 0:
                            command.invoke(engine, callback);
                            break;
                        case 1:
                            command.invoke(engine, request.args(1), callback);
                            break;
                        case 2:
                            sig = sig.substring(1);
                            if (sig.equals("s")) {
                                command.invoke(engine, request.args(1), request.args(2), callback);
                            } else if (sig.equals("i")) {
                                command.invoke(engine, request.args(1), request.argi(2), callback);
                            } else if (sig.equals("f")) {
                                command.invoke(engine, request.args(1), request.argf(2), callback);
                            } else if (sig.equals("S")) {
                                command.invoke(engine, request.args(1), request.argS(2), callback);
                            } else if (sig.equals("I")) {
                                command.invoke(engine, request.args(1), request.argI(2), callback);
                            } else if (sig.equals("F")) {
                                command.invoke(engine, request.args(1), request.argF(2), callback);
                            }
                            break;
                        case 3:
                            sig = sig.substring(1);
                            if (sig.equals("ss")) {
                                command.invoke(engine, request.args(1), request.args(2), request.args(3), callback);
                            } else if (sig.equals("si")) {
                                command.invoke(engine, request.args(1), request.args(2), request.argi(3), callback);
                            } else if (sig.equals("sf")) {
                                command.invoke(engine, request.args(1), request.args(2), request.argf(3), callback);
                            } else if (sig.equals("sS")) {
                                command.invoke(engine, request.args(1), request.args(2), request.argS(3), callback);
                            } else if (sig.equals("sI")) {
                                command.invoke(engine, request.args(1), request.args(2), request.argI(3), callback);
                            } else if (sig.equals("sF")) {
                                command.invoke(engine, request.args(1), request.args(2), request.argF(3), callback);
                            } else if (sig.equals("is")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.args(3), callback);
                            } else if (sig.equals("ii")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.argi(3), callback);
                            } else if (sig.equals("if")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.argf(3), callback);
                            } else if (sig.equals("iS")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.argS(3), callback);
                            } else if (sig.equals("iI")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.argI(3), callback);
                            } else if (sig.equals("iF")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.argF(3), callback);
                            } else if (sig.equals("fs")) {
                                command.invoke(engine, request.args(1), request.argf(2), request.args(3), callback);
                            } else if (sig.equals("fi")) {
                                command.invoke(engine, request.args(1), request.argf(2), request.argi(3), callback);
                            } else if (sig.equals("ff")) {
                                command.invoke(engine, request.args(1), request.argf(2), request.argf(3), callback);
                            } else if (sig.equals("fS")) {
                                command.invoke(engine, request.args(1), request.argf(2), request.argS(3), callback);
                            } else if (sig.equals("fI")) {
                                command.invoke(engine, request.args(1), request.argf(2), request.argI(3), callback);
                            }
                            break;
                        case 4:
                            sig = sig.substring(1);
                            if (sig.equals("sisi")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.args(3),
                                        request.argi(4), callback);
                            } else if (sig.equals("sisI")) {
                                command.invoke(engine, request.args(1), request.argi(2), request.args(3),
                                        request.argI(4), callback);
                            }
                            break;
                        }
                    } catch (Exception e) {
                        if (e instanceof IndexOutOfBoundsException) {
                            callback.error(String.format("Invalid arguments for command '%s'", request.name()));
                        } else {
                            callback.error(e.getMessage());
                        }
                        callback.response();
                    }
                }
            }
        });
    }

    public void close(int timeoutTs) {
        if (timeoutTs > 0) {
            execs.shutdown();
            try {
                if (!execs.awaitTermination(timeoutTs, TimeUnit.MILLISECONDS)) {
                    execs.shutdownNow();
                }
            } catch (InterruptedException ie) {
                execs.shutdownNow();
                Thread.currentThread().interrupt();
            }
        } else {
            execs.shutdownNow();
        }
    }

    public void clientClose(final AsyncChannel channel, final int status) {
        if (channel.closedRan == 0) { // server did not close it first
            // has close handler, execute it in another thread
            if (channel.closeHandler != null) {
                try {
                    // no need to maintain order
                    execs.submit(new Runnable() {
                        public void run() {
                            try {
                                channel.onClose(status);
                            } catch (Exception e) {
                                SimUtils.printError("on close handler", e);
                            }
                        }
                    });
                } catch (RejectedExecutionException e) {
                    SimUtils.printError("increase :queue-size if this happens often", e);
                }
            } else {
                // no close handler, mark the connection as closed
                // channel.closedRan = 1;
                // lazySet
                AsyncChannel.unsafe.putOrderedInt(channel, AsyncChannel.closedRanOffset, 1);
            }
        }
    }

}
TOP

Related Classes of com.guokr.simbase.server.ServerHandler

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