Skip to content

Commit a413f26

Browse files
committed
Enable parallel http server downloads
1 parent befb8f7 commit a413f26

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

modules/mods/httpserver/src/dist/httpserver.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ depend.ondemand=true
1717
# Sets a different address for the HTTP server to bind to. Can be 0.0.0.0 to
1818
# bind to all interfaces. Default is external ip in server settings.
1919
#internalServerAddress=
20+
# Maximum number of threads to server downloads in parallel
21+
#maxThreads=50

modules/mods/httpserver/src/main/java/org/gotti/wurmunlimited/mods/httpserver/HttpServerMod.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99
import org.gotti.wurmunlimited.modloader.interfaces.Initable;
1010
import org.gotti.wurmunlimited.modloader.interfaces.ModEntry;
1111
import org.gotti.wurmunlimited.modloader.interfaces.ModListener;
12+
import org.gotti.wurmunlimited.modloader.interfaces.ServerShutdownListener;
1213
import org.gotti.wurmunlimited.modloader.interfaces.ServerStartedListener;
1314
import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod;
1415

15-
public class HttpServerMod implements WurmServerMod, Initable, Configurable, ServerStartedListener, ModListener {
16+
public class HttpServerMod implements WurmServerMod, Initable, Configurable, ServerStartedListener, ServerShutdownListener, ModListener {
1617

1718
private Logger logger = Logger.getLogger(HttpServerMod.class.getName());
1819

1920
private int serverPort = 0;
2021
private String publicServerAddress = null;
2122
private String internalServerAddress = null;
2223
private int publicServerPort = 0;
24+
private int maxThreads = 50;
2325

2426
@Override
2527
public void init() {
@@ -31,13 +33,16 @@ public void configure(Properties properties) {
3133
this.publicServerPort = Integer.parseInt(properties.getProperty("publicServerPort", Integer.toString(publicServerPort)));
3234
this.publicServerAddress = properties.getProperty("publicServerAddress");
3335
this.internalServerAddress = properties.getProperty("internalServerAddress");
36+
this.maxThreads = Integer.parseInt(properties.getProperty("maxThreads", Integer.toString(maxThreads)));
3437

3538
logger.info("serverPort: " + serverPort);
3639
logger.info("publicServerAddress: " + publicServerAddress);
3740
logger.info("publicServerPort: " + publicServerPort);
3841
logger.info("internalServerAddress: " + internalServerAddress);
42+
logger.info("maxThreads: " + maxThreads);
3943

4044
ModHttpServerImpl.getInstance().configure(this.internalServerAddress, this.serverPort, this.publicServerAddress, this.publicServerPort);
45+
ModHttpServerImpl.getInstance().setMaxThreads(maxThreads);
4146
}
4247

4348
@Override
@@ -49,6 +54,15 @@ public void onServerStarted() {
4954
}
5055
}
5156

57+
@Override
58+
public void onServerShutdown() {
59+
try {
60+
ModHttpServerImpl.getInstance().stop();
61+
} catch (IOException e) {
62+
logger.log(Level.SEVERE, e.getMessage(), e);
63+
}
64+
}
65+
5266
@Override
5367
public void modInitialized(ModEntry<?> entry) {
5468
ModHttpServerImpl.getInstance().addModEntry(entry);

modules/mods/httpserver/src/main/java/org/gotti/wurmunlimited/mods/httpserver/ModHttpServerImpl.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ private static class Handler {
4141
private int publicServerPort = 0;
4242
private String publicServerAddress = null;
4343
private String internalServerAddress = null;
44+
private int maxThreads = 10;
4445

4546
private PackServer packServer;
4647

@@ -105,15 +106,38 @@ public String serve(WurmServerMod mod, Pattern regex, Path file) {
105106
return serve(mod, regex, path -> readFile(file));
106107
}
107108

109+
/**
110+
* Start the http server
111+
* @throws IOException
112+
*/
108113
protected void start() throws IOException {
109-
this.packServer = new PackServer(port, publicServerAddress, publicServerPort, internalServerAddress) {
114+
this.packServer = new PackServer(port, publicServerAddress, publicServerPort, internalServerAddress, maxThreads) {
110115
@Override
111116
protected InputStream getStream(String path) throws IOException {
112117
return handle(path);
113118
}
114119
};
115120
}
116121

122+
/**
123+
* Stop the http server
124+
* @throws IOException
125+
*/
126+
protected void stop() throws IOException {
127+
if (this.packServer != null) {
128+
this.packServer.stop();
129+
this.packServer = null;
130+
}
131+
}
132+
133+
/**
134+
* Set maximum number of threads serving parallel downloads
135+
* @param maxThreads maximum number of thread
136+
*/
137+
protected void setMaxThreads(int maxThreads) {
138+
this.maxThreads = maxThreads;
139+
}
140+
117141
private InputStream handle(String path) {
118142
for (Handler handler : handlers) {
119143
final Matcher matcher = handler.modName.matcher(path);
@@ -142,6 +166,9 @@ public boolean isRunning() {
142166

143167
@Override
144168
public URI getUri() throws URISyntaxException {
145-
return packServer.getUri();
169+
if (packServer != null) {
170+
return packServer.getUri();
171+
}
172+
return null;
146173
}
147174
}

modules/mods/httpserver/src/main/java/org/gotti/wurmunlimited/mods/httpserver/PackServer.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
import java.net.InetSocketAddress;
88
import java.net.URI;
99
import java.net.URISyntaxException;
10+
import java.util.concurrent.ExecutorService;
11+
import java.util.concurrent.SynchronousQueue;
12+
import java.util.concurrent.ThreadPoolExecutor;
13+
import java.util.concurrent.TimeUnit;
1014
import java.util.logging.Level;
1115
import java.util.logging.Logger;
1216

@@ -15,16 +19,19 @@
1519
import com.sun.net.httpserver.HttpServer;
1620
import com.wurmonline.server.Server;
1721

22+
@SuppressWarnings("restriction")
1823
public abstract class PackServer {
1924

20-
private Logger logger = Logger.getLogger(PackServer.class.getName());
25+
private final Logger logger = Logger.getLogger(PackServer.class.getName());
2126

22-
private HttpServer httpServer;
27+
private final HttpServer httpServer;
2328

2429
private final String publicServerAddress;
2530
private final int publicServerPort;
2631

27-
public PackServer(int port, String publicServerAddress, int publicServerPort, String internalServerAddress) throws IOException {
32+
private final ExecutorService executor;
33+
34+
public PackServer(int port, String publicServerAddress, int publicServerPort, String internalServerAddress, int maxThreads) throws IOException {
2835

2936
this.publicServerAddress = publicServerAddress;
3037
this.publicServerPort = publicServerPort;
@@ -34,9 +41,12 @@ public PackServer(int port, String publicServerAddress, int publicServerPort, St
3441
addr = InetAddress.getByAddress(Server.getInstance().getExternalIp());
3542
else
3643
addr = InetAddress.getByName(internalServerAddress);
44+
45+
executor = new ThreadPoolExecutor(0, maxThreads, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
3746

3847
InetSocketAddress address = new InetSocketAddress(addr, port);
3948
httpServer = HttpServer.create(address, 0);
49+
httpServer.setExecutor(executor);
4050
httpServer.createContext("/", new HttpHandler() {
4151

4252
@Override
@@ -83,5 +93,14 @@ public URI getUri() throws URISyntaxException {
8393
return new URI("http", null, address, port, "/", null, null);
8494
}
8595

96+
public void stop() throws IOException {
97+
httpServer.stop(0);
98+
executor.shutdown();
99+
try {
100+
executor.awaitTermination(60, TimeUnit.SECONDS);
101+
} catch (InterruptedException e) {
102+
throw new IOException(e);
103+
}
104+
}
86105

87106
}

0 commit comments

Comments
 (0)