diff --git a/pom.xml b/pom.xml index 65b50cd3..9be25fb5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,8 +10,7 @@ 11 11 - 4.6.3 - [1.7.16,) + 1.7.16 3.25.3 5.8.2 2.2.2 @@ -54,11 +53,6 @@ 3.10.1 - - info.picocli - picocli-codegen - ${picocli.version} - org.openjdk.jmh jmh-generator-annprocess @@ -196,9 +190,9 @@ 1 - info.picocli - picocli - ${picocli.version} + commons-cli + commons-cli + 1.6.0 org.slf4j diff --git a/unknow-server-http/src/main/java/unknow/server/http/AbstractHttpServer.java b/unknow-server-http/src/main/java/unknow/server/http/AbstractHttpServer.java index e55a8045..8b667247 100644 --- a/unknow-server-http/src/main/java/unknow/server/http/AbstractHttpServer.java +++ b/unknow-server-http/src/main/java/unknow/server/http/AbstractHttpServer.java @@ -1,5 +1,6 @@ package unknow.server.http; +import java.net.InetSocketAddress; import java.util.ServiceLoader; import java.util.concurrent.ExecutorService; import java.util.concurrent.SynchronousQueue; @@ -7,97 +8,99 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; + import jakarta.servlet.ServletContainerInitializer; import jakarta.servlet.ServletException; -import picocli.CommandLine.Option; import unknow.server.http.servlet.FilterConfigImpl; import unknow.server.http.servlet.ServletConfigImpl; import unknow.server.http.servlet.ServletContextImpl; import unknow.server.http.utils.EventManager; import unknow.server.http.utils.ServletManager; -import unknow.server.nio.cli.NIOServerCli; +import unknow.server.nio.NIOServer; +import unknow.server.nio.NIOServerBuilder; /** * Abstract server * * @author unknow */ -public abstract class AbstractHttpServer extends NIOServerCli { - - /** - * public vhost seen be the servlet (default to the binded address) - */ - @Option(names = "--vhost", description = "public vhost seen be the servlet (default to the binded address)", descriptionKey = "vhost") - public String vhost; - - /** - * min number of execution thread to use, default to 0 - */ - @Option(names = "--exec-min", description = "min number of exec thread to use, default to 0", descriptionKey = "exec-min") - public int execMin = 0; - - /** - * max number of execution thread to use, default to Integer.MAX_VALUE - */ - @Option(names = "--exec-max", description = "max number of exec thread to use, default to Integer.MAX_VALUE", descriptionKey = "exec-max") - public int execMax = Integer.MAX_VALUE; - - /** - * max idle time for exec thread, default to 60 - */ - @Option(names = "--exec-idle", description = "max idle time for exec thread in seconds, default to 60", descriptionKey = "exec-idle") - public long execIdle = 60L; - - /** - * max time to keep idle keepalive connection, default to -1 - */ - @Option(names = "--keep-alive-idle", description = "max time to keep idle keepalive connection, -1: infinite, 0: no keep alive, default to -1", descriptionKey = "keep-alive-idle") - public int keepAliveIdle = 2000; - - protected final ServletContextImpl ctx; - protected final ServletManager servlets; - protected final EventManager events; - - protected AbstractHttpServer() { - servlets = createServletManager(); - events = createEventManager(); - ctx = createContext(); - } +public abstract class AbstractHttpServer extends NIOServerBuilder { + private Opt addr; + private Opt vhost; + private Opt execMin; + private Opt execMax; + private Opt execIdle; + private Opt keepAlive; + + protected ServletContextImpl ctx; + protected ServletManager servlets; + protected EventManager events; protected abstract ServletManager createServletManager(); protected abstract EventManager createEventManager(); - protected abstract ServletContextImpl createContext(); + protected abstract ServletContextImpl createContext(String vhost); protected abstract ServletConfigImpl[] createServlets(); protected abstract FilterConfigImpl[] createFilters(); - protected void loadInitializer() throws ServletException { - for (ServletContainerInitializer i : ServiceLoader.load(ServletContainerInitializer.class)) { - i.onStartup(null, ctx); - } + @Override + protected void beforeParse() { + addr = withOpt("addr").withCli(Option.builder("a").longOpt("addr").hasArg().desc("address to bind to").build()).withValue(":8080"); + vhost = withOpt("vhost").withCli(Option.builder().longOpt("vhost").desc("public vhost seen by the servlet, default to the binded address").build()); + execMin = withOpt("exec-min").withCli(Option.builder().longOpt("exec-min").desc("min number of exec thread to use").build()).withValue("0"); + execMax = withOpt("exec-max").withCli(Option.builder().longOpt("exec-max").desc("max number of exec thread to use").build()) + .withValue(Integer.toString(Integer.MAX_VALUE)); + execIdle = withOpt("exec-idle").withCli(Option.builder().longOpt("exec-idle").desc("max idle time for exec thread in seconds").build()).withValue("60"); + keepAlive = withOpt("exec-idle") + .withCli(Option.builder().longOpt("exec-idle").desc("max time to keep idle keepalive connection, -1: infinite, 0: no keep alive").build()).withValue("2000"); } @Override - protected final void init() throws Exception { - AtomicInteger i = new AtomicInteger(); - ExecutorService executor = new ThreadPoolExecutor(execMin, execMax, execIdle, TimeUnit.SECONDS, new SynchronousQueue<>(), r -> { - Thread t = new Thread(r, "exec-" + i.getAndIncrement()); - t.setDaemon(true); - return t; - }); + protected void process(NIOServer server, CommandLine cli) throws Exception { + InetSocketAddress address = parseAddr(cli, addr, ""); + String value = cli.getOptionValue(vhost.name()); + if (value == null) + value = address.getHostString(); - handler = () -> new HttpConnection(executor, ctx, keepAliveIdle); + servlets = createServletManager(); + events = createEventManager(); + ctx = createContext(value); loadInitializer(); servlets.initialize(ctx, createServlets(), createFilters()); events.fireContextInitialized(ctx); + + AtomicInteger i = new AtomicInteger(); + ExecutorService executor = new ThreadPoolExecutor(parseInt(cli, execMin, 0), parseInt(cli, execMax, 0), parseInt(cli, execIdle, 0), TimeUnit.SECONDS, + new SynchronousQueue<>(), r -> { + Thread t = new Thread(r, "exec-" + i.getAndIncrement()); + t.setDaemon(true); + return t; + }); + int keepAliveIdle = parseInt(cli, keepAlive, -1); + server.bind(address, () -> new HttpConnection(executor, ctx, keepAliveIdle)); } - @Override - protected final void destroy() { - events.fireContextDestroyed(ctx); + protected void loadInitializer() throws ServletException { + for (ServletContainerInitializer i : ServiceLoader.load(ServletContainerInitializer.class)) { + i.onStartup(null, ctx); + } + } + + public void process(String[] arg) throws Exception { + NIOServer nioServer = build(arg); + try { + nioServer.start(); + nioServer.await(); + } finally { + nioServer.stop(); + nioServer.await(); + events.fireContextDestroyed(ctx); + } } } diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/CreateContext.java b/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/CreateContext.java index 2bf0b59b..42ddafaf 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/CreateContext.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/CreateContext.java @@ -4,15 +4,8 @@ package unknow.server.maven.servlet.builder; import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.expr.AssignExpr; -import com.github.javaparser.ast.expr.BinaryExpr; -import com.github.javaparser.ast.expr.BinaryExpr.Operator; -import com.github.javaparser.ast.expr.ConditionalExpr; import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.NullLiteralExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.IfStmt; import com.github.javaparser.ast.stmt.ReturnStmt; import unknow.server.http.servlet.ServletContextImpl; @@ -31,13 +24,7 @@ public void add(BuilderContext ctx) { TypeCache t = ctx.type(); ctx.self().addMethod("createContext", Modifier.Keyword.PROTECTED, Modifier.Keyword.FINAL).setType(t.getClass(ServletContextImpl.class)) - .addMarkerAnnotation(Override.class).createBody() - .addStatement(new IfStmt(new BinaryExpr(new NameExpr("vhost"), new NullLiteralExpr(), Operator.EQUALS), - new ExpressionStmt(new AssignExpr(new NameExpr("vhost"), - new ConditionalExpr(new BinaryExpr(new NameExpr("address"), new NullLiteralExpr(), Operator.EQUALS), Utils.text("localhost"), - new NameExpr("address")), - AssignExpr.Operator.ASSIGN)), - null)) + .addParameter(String.class, "vhost").addMarkerAnnotation(Override.class).createBody() .addStatement(new ReturnStmt(new ObjectCreationExpr(null, t.getClass(ServletContextImpl.class), Utils.list(Utils.text(ctx.descriptor().name), new NameExpr("vhost"), Utils.mapString(ctx.descriptor().param, t), Names.SERVLETS, Names.EVENTS, new ObjectCreationExpr(null, t.getClass(ctx.sessionFactory()), Utils.list()), Utils.mapString(ctx.descriptor().localeMapping, t), diff --git a/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/Main.java b/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/Main.java index a019c898..ebb8af16 100644 --- a/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/Main.java +++ b/unknow-server-maven/src/main/java/unknow/server/maven/servlet/builder/Main.java @@ -7,9 +7,7 @@ import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.TypeExpr; -import picocli.CommandLine; import unknow.server.maven.TypeCache; import unknow.server.maven.Utils; import unknow.server.maven.servlet.Builder; @@ -22,9 +20,7 @@ public class Main extends Builder { @Override public void add(BuilderContext ctx) { TypeCache t = ctx.type(); - ctx.self().addMethod("main", Modifier.Keyword.PUBLIC, Modifier.Keyword.STATIC) - .addParameter(String[].class, "arg") - .createBody() - .addStatement(new MethodCallExpr(new TypeExpr(t.getClass(System.class)), "exit").addArgument(new MethodCallExpr(new ObjectCreationExpr(null, t.getClass(CommandLine.class), Utils.list(new ObjectCreationExpr(null, t.getClass(ctx.self()), Utils.list()))), "execute").addArgument(new NameExpr("arg")))); + ctx.self().addMethod("main", Modifier.Keyword.PUBLIC, Modifier.Keyword.STATIC).addParameter(String[].class, "arg").addThrownException(t.getClass(Exception.class)) + .createBody().addStatement(new MethodCallExpr(new ObjectCreationExpr(null, t.getClass(ctx.self()), Utils.list()), "process", Utils.list(new NameExpr("arg")))); } } diff --git a/unknow-server-nio/pom.xml b/unknow-server-nio/pom.xml index f0e39577..937adc25 100644 --- a/unknow-server-nio/pom.xml +++ b/unknow-server-nio/pom.xml @@ -14,8 +14,8 @@ ${project.version} - info.picocli - picocli + commons-cli + commons-cli \ No newline at end of file diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/NIOServer.java b/unknow-server-nio/src/main/java/unknow/server/nio/NIOServer.java index fbaa1891..2ce91f64 100644 --- a/unknow-server-nio/src/main/java/unknow/server/nio/NIOServer.java +++ b/unknow-server-nio/src/main/java/unknow/server/nio/NIOServer.java @@ -8,16 +8,11 @@ import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.Function; import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import unknow.server.util.pool.Pool; - /** * the NIO Server * @@ -31,8 +26,6 @@ public class NIOServer extends NIOLoop { /** the listener */ private final NIOServerListener listener; - private final Map, ? extends NIOConnection>, Pool> pools; - /** * create new Server * @@ -45,7 +38,6 @@ public NIOServer(NIOWorkers workers, NIOServerListener listener) throws IOExcept super("NIOServer", 0); this.workers = workers; this.listener = listener == null ? NIOServerListener.NOP : listener; - this.pools = new IdentityHashMap<>(); } /** diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/NIOServerBuilder.java b/unknow-server-nio/src/main/java/unknow/server/nio/NIOServerBuilder.java new file mode 100644 index 00000000..1ea65085 --- /dev/null +++ b/unknow-server-nio/src/main/java/unknow/server/nio/NIOServerBuilder.java @@ -0,0 +1,187 @@ +package unknow.server.nio; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import unknow.server.nio.NIOWorkers.RoundRobin; + +public class NIOServerBuilder { + private static final Logger logger = LoggerFactory.getLogger(NIOServerBuilder.class); + + private final Option help = Option.builder("h").longOpt("help").desc("show this help").build(); + private final List options = new ArrayList<>(); + + private Opt iothread; + private Opt select; + private Opt listener; + private Opt shutdown; + + public NIOServerBuilder() { + iothread = withOpt("iothread").withCli(Option.builder().longOpt("iothread").argName("num").hasArg().type(Integer.class).desc("number of io thread to use").build()) + .withValue(Integer.toString(Runtime.getRuntime().availableProcessors())); + select = withOpt("select").withCli(Option.builder().longOpt("select").argName("num").hasArg().type(Integer.class).desc("timeout on Selector.select").build()) + .withValue("200"); + listener = withOpt("listener").withCli(Option.builder().longOpt("listener").argName("NOP|LOG").hasArg().type(String.class).desc("set the listener").build()) + .withValue("NOP"); + shutdown = withOpt("shutdown").withCli( + Option.builder().longOpt("shutdown").argName("port|addr:port").hasArg().type(Integer.class).desc("addr:port to gracefuly shutdown the server").build()); + } + + public Opt withOpt(String name) { + Opt o = new Opt(name); + options.add(o); + return o; + } + + protected void beforeParse() { + // for override + } + + public static int parseInt(CommandLine cli, Opt o, int min) { + try { + int i = Integer.parseInt(o.value(cli)); + if (i < min) + throw new IllegalArgumentException(o.name() + " should be >= " + min); + return i; + } catch (@SuppressWarnings("unused") NumberFormatException e) { + throw new IllegalArgumentException(o.name() + " invalid value " + o.value(cli)); + } + } + + public static InetSocketAddress parseAddr(CommandLine cli, Opt o, String defaultHost) { + String host = defaultHost; + String a = o.value(cli); + if (a == null) + return null; + int i = a.indexOf(':'); + if (i == 0) + a = a.substring(1); + else if (i > 0) { + host = a.substring(0, i); + a = a.substring(i + 1); + } + try { + int port = Integer.parseInt(a); + if (host == null || host.isEmpty()) + return new InetSocketAddress(port); + return new InetSocketAddress(host, port); + } catch (@SuppressWarnings("unused") NumberFormatException e) { + throw new IllegalArgumentException(o.name() + " invalid value " + o.value(cli)); + } + } + + @SuppressWarnings("unused") + protected void process(NIOServer server, CommandLine cli) throws Exception { + // for override + } + + public final NIOServer build(String... arg) throws Exception { + beforeParse(); + readProperties(); + Options opts = new Options(); + opts.addOption(help); + for (Opt o : options) { + if (o.cli != null) + opts.addOption(o.cli); + } + + CommandLine cli = new DefaultParser().parse(opts, arg); + if (cli.hasOption(help)) { + HelpFormatter helpFormatter = new HelpFormatter(); + helpFormatter.setWidth(100); + helpFormatter.printHelp("nioserver", opts); + System.exit(2); + } + + NIOServerListener l = getListener(listener.value(cli)); + + NIOWorkers workers = createWorkers(parseInt(cli, iothread, 0), parseInt(cli, select, 0), l); + + NIOServer server = new NIOServer(workers, l); + process(server, cli); + InetSocketAddress addr = parseAddr(cli, shutdown, "127.0.0.1"); + if (addr != null) + server.bind(addr, () -> new ShutdownConnection(server)); + return server; + } + + private NIOWorkers createWorkers(int i, int selectTime, NIOServerListener l) throws IOException { + if (i == 1) + return new NIOWorker(0, l, selectTime); + NIOWorker[] w = new NIOWorker[i]; + while (i > 0) + w[--i] = new NIOWorker(i, l, selectTime); + return new RoundRobin(w); + } + + private NIOServerListener getListener(String l) { + if ("NOP".equals(l)) + return NIOServerListener.NOP; + if ("LOG".equals(l)) + return NIOServerListener.LOG; + throw new IllegalArgumentException("listener should be one of NOP, LOG"); + } + + private void readProperties() { + try (InputStream is = this.getClass().getResourceAsStream("/META-INF/nioserver.properties")) { + if (is == null) + return; + Properties prop = new Properties(); + try (Reader r = new InputStreamReader(is, StandardCharsets.UTF_8)) { + prop.load(r); + } + for (Opt o : options) { + String v = (String) prop.get(o.name); + if (v != null) + o.value = v; + } + } catch (IOException e) { + logger.warn("Failed to read nioserver.properties", e); + } + } + + public static class Opt { + private final String name; + private Option cli; + private String value; + + public Opt(String name) { + this.name = name; + } + + public Opt withValue(String value) { + if (cli != null) + cli.setDescription(cli.getDescription() + ", default to: " + value); + this.value = value; + return this; + } + + public Opt withCli(Option cli) { + this.cli = cli; + return this; + } + + public String name() { + return name; + } + + public String value(CommandLine c) { + return cli != null ? c.getOptionValue(cli, value) : value; + } + } +} diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/cli/ShutdownConnection.java b/unknow-server-nio/src/main/java/unknow/server/nio/ShutdownConnection.java similarity index 74% rename from unknow-server-nio/src/main/java/unknow/server/nio/cli/ShutdownConnection.java rename to unknow-server-nio/src/main/java/unknow/server/nio/ShutdownConnection.java index 20793c5d..dfdaa3e3 100644 --- a/unknow-server-nio/src/main/java/unknow/server/nio/cli/ShutdownConnection.java +++ b/unknow-server-nio/src/main/java/unknow/server/nio/ShutdownConnection.java @@ -1,10 +1,7 @@ /** * */ -package unknow.server.nio.cli; - -import unknow.server.nio.NIOConnection; -import unknow.server.nio.NIOServer; +package unknow.server.nio; public class ShutdownConnection extends NIOConnection { private final NIOServer server; diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/cli/DefaultOptionProvider.java b/unknow-server-nio/src/main/java/unknow/server/nio/cli/DefaultOptionProvider.java deleted file mode 100644 index 676ed4fc..00000000 --- a/unknow-server-nio/src/main/java/unknow/server/nio/cli/DefaultOptionProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * - */ -package unknow.server.nio.cli; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.Properties; - -import picocli.CommandLine.IDefaultValueProvider; -import picocli.CommandLine.Model.ArgSpec; - -/** - * @author unknow - */ -public class DefaultOptionProvider implements IDefaultValueProvider { - private final Properties prop; - - /** - * create new DefaultOptionProvider - * - * @throws IOException in case of error - */ - public DefaultOptionProvider() throws IOException { - prop = new Properties(); - try (InputStream is = this.getClass().getResourceAsStream("/META-INF/nioserver.properties")) { - if (is == null) - return; - try (Reader r = new InputStreamReader(is, StandardCharsets.UTF_8)) { - prop.load(r); - } - } - } - - @Override - public String defaultValue(ArgSpec arg) throws Exception { - return prop.getProperty(arg.command().qualifiedName(".") + "." + arg.descriptionKey()); - } -} diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOListenerConverter.java b/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOListenerConverter.java deleted file mode 100644 index 2327e9b6..00000000 --- a/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOListenerConverter.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * - */ -package unknow.server.nio.cli; - -import java.lang.reflect.InvocationTargetException; - -import picocli.CommandLine.ITypeConverter; -import picocli.CommandLine.TypeConversionException; -import unknow.server.nio.NIOServerListener; - -/** - * @author unknow - */ -public class NIOListenerConverter implements ITypeConverter { - @Override - public NIOServerListener convert(String value) throws Exception { - String[] split = value.split(";"); - if (split.length == 1) - return get(split[0]); - NIOServerListener[] listeners = new NIOServerListener[split.length]; - for (int i = 0; i < split.length; i++) - listeners[i] = get(split[i]); - return new NIOServerListener.Composite(listeners); - } - - private static NIOServerListener get(String s) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { - if ("NOP".equals(s)) - return NIOServerListener.NOP; - if ("LOG".equals(s)) - return NIOServerListener.LOG; - Class forName = Class.forName(s); - if (!NIOServerListener.class.isAssignableFrom(forName)) - throw new TypeConversionException("class '" + forName + "' doesn't implements NIOServerListener"); - return (NIOServerListener) forName.getDeclaredConstructor().newInstance(); - } -} diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOServerCli.java b/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOServerCli.java deleted file mode 100644 index e756fafb..00000000 --- a/unknow-server-nio/src/main/java/unknow/server/nio/cli/NIOServerCli.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * - */ -package unknow.server.nio.cli; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.concurrent.Callable; -import java.util.function.Supplier; - -import picocli.CommandLine; -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; -import unknow.server.nio.NIOConnection; -import unknow.server.nio.NIOServer; -import unknow.server.nio.NIOServerListener; -import unknow.server.nio.NIOWorker; -import unknow.server.nio.NIOWorkers; -import unknow.server.nio.NIOWorkers.RoundRobin; - -/** - * NioServer configuration - * - * @author Unknow - */ -@Command(name = "nioserver", defaultValueProvider = DefaultOptionProvider.class) -public class NIOServerCli implements Callable { - - /** address to bind to */ - @Option(names = { "-a", "--address" }, description = "address to bind to, default to all interface", descriptionKey = "address") - public String address; - - /** port the server will listen on */ - @Option(names = { "-p", "--port" }, required = true, description = "port the server will listen on", descriptionKey = "port") - public int port; - - /** handler factory */ -// @Option(names = "--handler", descriptionKey = "handler", converter = ObjectConverter.class) - public Supplier handler; - - /** number of io thread to use, default to the number of CPU */ - @Option(names = "--iothread", description = "number of io thread to use, default to the number of CPU", descriptionKey = "iothread") - public int iothread = Math.max(1, Runtime.getRuntime().availableProcessors() / 2); - - /** server listener */ - @Option(names = "--listener", description = "set the listener, default to NOP", descriptionKey = "listener", converter = NIOListenerConverter.class) - public NIOServerListener listener = NIOServerListener.NOP; - - /** selectionTime */ - @Option(names = "--selecttime", description = "timeout on Selector.select, 0=unlimited", descriptionKey = "selecttime") - public long selectTime = 200; - - /** shutdown port */ - @Option(names = "--shutdown-port", description = "port to open to gracefuly shutdown the server", descriptionKey = "shutdown-port") - public int shutdownPort = 0; - - /** - * @return local address to bind to - */ - public InetSocketAddress getInetAddress() { - if (address == null) - return new InetSocketAddress(port); - return new InetSocketAddress(address, port); - } - - /** - * called before the server start but after the property are parsed - */ - protected void init() throws Exception { // OK - } - - /** - * called after the server shut down - */ - protected void destroy() throws Exception { // OK - } - - @Override - public final Integer call() throws Exception { - init(); - if (selectTime < 0) - throw new IllegalArgumentException("selectTime should not be <0"); - - NIOWorkers workers; - if (iothread == 1) - workers = new NIOWorker(0, listener, selectTime); - else { - NIOWorker[] w = new NIOWorker[iothread]; - for (int i = 0; i < iothread; i++) - w[i] = new NIOWorker(i, listener, selectTime); - workers = new RoundRobin(w); - } - - NIOServer nioServer = new NIOServer(workers, listener); - try { - nioServer.bind(getInetAddress(), handler); - if (shutdownPort > 0) - nioServer.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), shutdownPort), () -> new ShutdownConnection(nioServer)); - nioServer.start(); - nioServer.await(); - } finally { - nioServer.stop(); - nioServer.await(); - destroy(); - } - return 0; - } - - /** - * the main - * - * @param arg cli param - */ - public static void main(String[] arg) { - System.exit(new CommandLine(new NIOServerCli()).execute(arg)); - } -} \ No newline at end of file diff --git a/unknow-server-nio/src/main/java/unknow/server/nio/cli/ObjectConverter.java b/unknow-server-nio/src/main/java/unknow/server/nio/cli/ObjectConverter.java deleted file mode 100644 index 0efcfca3..00000000 --- a/unknow-server-nio/src/main/java/unknow/server/nio/cli/ObjectConverter.java +++ /dev/null @@ -1,16 +0,0 @@ -/** - * - */ -package unknow.server.nio.cli; - -import picocli.CommandLine.ITypeConverter; - -/** - * @author unknow - */ -public class ObjectConverter implements ITypeConverter { - @Override - public Object convert(String value) throws Exception { - return Class.forName(value).getDeclaredConstructor().newInstance(); - } -} diff --git a/unknow-server-test/unknow-server-test-jar/src/main/resources/META-INF/nioserver.properties b/unknow-server-test/unknow-server-test-jar/src/main/resources/META-INF/nioserver.properties index 60cf68c6..d6433f30 100644 --- a/unknow-server-test/unknow-server-test-jar/src/main/resources/META-INF/nioserver.properties +++ b/unknow-server-test/unknow-server-test-jar/src/main/resources/META-INF/nioserver.properties @@ -1,2 +1,2 @@ -nioserver.port=8080 -nioserver.listener=NOP \ No newline at end of file +addr=8080 +listener=NOP \ No newline at end of file