
be.bagofwords.application.SocketServer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bow-utils Show documentation
Show all versions of bow-utils Show documentation
Utility classes that are used in the count-db project and other bow-* projects
The newest version!
package be.bagofwords.application;
import be.bagofwords.application.status.StatusViewable;
import be.bagofwords.ui.UI;
import be.bagofwords.util.*;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.*;
/**
* Created by koen on 01.11.16.
*/
public class SocketServer extends SafeThread implements StatusViewable {
public static final String ENCODING = "UTF-8";
public static final long LONG_ERROR = Long.MAX_VALUE;
public static final long LONG_OK = Long.MAX_VALUE - 1;
public static final long LONG_END = Long.MAX_VALUE - 2;
private ServerSocket serverSocket;
private Map socketRequestHandlerFactories;
private final List runningRequestHandlers;
private final int scpPort;
private int totalNumberOfConnections;
public SocketServer(int port) {
super("socket_server", false);
this.runningRequestHandlers = new ArrayList<>();
this.scpPort = port;
this.totalNumberOfConnections = 0;
this.socketRequestHandlerFactories = new HashMap<>();
try {
this.serverSocket = new ServerSocket(scpPort);
} catch (IOException exp) {
this.serverSocket = null;
throw new RuntimeException("Failed to initialize server " + getName() + " on port " + scpPort, exp);
}
}
public synchronized void registerSocketRequestHandlerFactory(SocketRequestHandlerFactory factory) {
if (socketRequestHandlerFactories.containsKey(factory.getName())) {
throw new RuntimeException("A SocketRequestHandlerFactory was already registered with name " + factory.getName());
}
socketRequestHandlerFactories.put(factory.getName(), factory);
}
@Override
protected void runInt() throws Exception {
UI.write("Started server " + getName() + " on port " + scpPort);
while (!serverSocket.isClosed() && !isTerminateRequested()) {
try {
Socket acceptedSocket = serverSocket.accept();
SocketConnection connection = new UnbufferedSocketConnection(acceptedSocket);
String factoryName = connection.readString();
if(factoryName==null || StringUtils.isEmpty(factoryName.trim())) {
connection.writeLong(SocketServer.LONG_ERROR);
connection.writeString("No name specified for the requested SocketRequestHandlerFactory");
continue;
}
SocketRequestHandlerFactory factory = socketRequestHandlerFactories.get(factoryName);
if (factory == null) {
UI.writeWarning("No SocketRequestHandlerFactory registered for name " + factoryName);
connection.writeLong(SocketServer.LONG_ERROR);
connection.writeString("No SocketRequestHandlerFactory registered for name " + factoryName);
continue;
}
SocketRequestHandler handler = factory.createSocketRequestHandler(acceptedSocket);
handler.setSocketServer(this);
if (handler != null) {
synchronized (runningRequestHandlers) {
runningRequestHandlers.add(handler);
}
handler.start();
totalNumberOfConnections++;
} else {
UI.writeWarning("Factory " + factoryName + " failed to create a socket handler. Closing socket...");
acceptedSocket.close();
}
} catch (IOException e) {
if (!(e instanceof SocketException || isTerminateRequested())) {
UI.writeError(e);
}
}
}
}
@Override
public void doTerminate() {
IOUtils.closeQuietly(serverSocket);
//once a request handler is finished, it removes itself from the list of requestHandlers, so we just wait until this list is empty
while (!runningRequestHandlers.isEmpty()) {
synchronized (runningRequestHandlers) {
for (SocketRequestHandler requestHandler : runningRequestHandlers) {
if (!requestHandler.isTerminateRequested()) {
requestHandler.terminate(); //we can not call terminateAndWaitForFinish() here since to finish the request handler needs access to the runningRequestHandlers list
}
}
}
Utils.threadSleep(10);
}
UI.write("Server " + getName() + " has been terminated.");
}
public int getTotalNumberOfConnections() {
return totalNumberOfConnections;
}
public List getRunningRequestHandlers() {
return runningRequestHandlers;
}
public void removeHandler(SocketRequestHandler handler) {
synchronized (runningRequestHandlers) {
runningRequestHandlers.remove(handler);
}
}
@Override
public void printHtmlStatus(StringBuilder sb) {
sb.append("Printing database server statistics
");
ln(sb, "");
ln(sb, "Used memory is " + UI.getMemoryUsage() + " ");
ln(sb, "Total number of connections " + getTotalNumberOfConnections() + " ");
List runningRequestHandlers = getRunningRequestHandlers();
ln(sb, "Current number of handlers " + runningRequestHandlers.size() + " ");
List sortedRequestHandlers;
synchronized (runningRequestHandlers) {
sortedRequestHandlers = new ArrayList<>(runningRequestHandlers);
}
Collections.sort(sortedRequestHandlers, (o1, o2) -> -Double.compare(o1.getTotalNumberOfRequests(), o2.getTotalNumberOfRequests()));
for (int i = 0; i < sortedRequestHandlers.size(); i++) {
SocketRequestHandler handler = sortedRequestHandlers.get(i);
ln(sb, "" + i + " Name " + handler.getName() + " ");
ln(sb, "" + i + " Started at " + new Date(handler.getStartTime()) + " ");
ln(sb, "" + i + " Total number of requests " + handler.getTotalNumberOfRequests() + " ");
double requestsPerSec = handler.getTotalNumberOfRequests() * 1000.0 / (System.currentTimeMillis() - handler.getStartTime());
ln(sb, "" + i + " Average requests/s " + NumUtils.fmt(requestsPerSec) + " ");
}
ln(sb, "
");
}
private void ln(StringBuilder sb, String s) {
sb.append(s);
sb.append("\n");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy