Commit 2dcd506f authored by Lubomir Bulej's avatar Lubomir Bulej

Clean up request dispatching a little bit

parent bb15cd61
......@@ -20,40 +20,41 @@ import ch.usi.dag.shvm.SHVMImpl;
final class RequestDispatcher {
* Pure static class.
private RequestDispatcher() {}
* Pass the messages to appropriate handlers and return {@link ServerMessage} containing
* the reply. When null is returned, then no reply will be sent.
* Dispatches the message to the appropriate handler. Returns a response to
* be sent to the client (including errors occurring during request
* processing) or {@code null} if no response should be sent.
* @param message
* @param context
* @return
* @throws ServerRuntimeException When a serious error during occurs during server runtime.
* @return {@link ServerMessage} with response to the request or
* {@code null} if no response is to be sent.
* @throws ServerRuntimeException
* If an internal server error occurs.
static ServerMessage dispatchMessage(
final ClientMessage message,
final Server.Context context
) throws ServerRuntimeException
ServerMessage serverMessage = null;
final ServerMessage.Builder builder = ServerMessage.newBuilder().setResponseId(message.getRequestId());
static ServerMessage dispatchMessage (
final ClientMessage message, final Server.Context context
) throws ServerRuntimeException {
final ServerMessage.Builder builder = ServerMessage.newBuilder ()
.setResponseId (message.getRequestId ());
try {
switch (message.getRequestCase()) {
switch (message.getRequestCase ()) {
serverMessage = handleSessionInit(context, message.getSessionInitRequest(), builder);
return handleSessionInit (
message.getSessionInitRequest (), context, builder
final Integer sessionID = message.getSessionId();
handleCloseConnection(context, sessionID);
// No response is returned when closing connection.
handleCloseConnection (message.getSessionId (), context);
return null;
serverMessage = InstrumentationRequestDispatcher.dispatchMessage(context, message, builder);
return InstrumentationRequestDispatcher.dispatchMessage (
message, context, builder
......@@ -62,75 +63,83 @@ final class RequestDispatcher {
serverMessage = AnalysisRequestDispatcher.dispatchMessage(context, message);
// Analysis messages don't provide responses.
AnalysisRequestDispatcher.dispatchMessage (message, context);
return null;
throw new ServerRuntimeException(
String.format("Cannot handle request case %s", message.getRequestCase().name())
// Internal error. Should be handled upstream.
throw new ServerRuntimeException (
"unable to handle request %s", message.getRequestCase ()
} catch (final RequestErrorException e) {"Sending error message to the client: [%s]", e.getLocalizedMessage());
serverMessage = builder
} catch (final RequestErrorException e) {
// Error while processing the request: notify the client.
// This is a "valid" outcome, upstream code does not need to know.
context.log.error ("failed to process request: %s", e.getMessage ());
return builder.setError (
Main.Error.newBuilder ().setMessage (e.getMessage ()).build ()
).build ();
return serverMessage;
* Register the session in the {@link SessionManager} instance and return {@link ServerMessage}
* acquiring the creation of session and containing the session id.
* Creates a new session and prepares a response for the client. The session
* is initialized with DiSL and/or Shadow VM runtime depending on what the
* client requested.
* @param context
* @param request
* @param context
* @return
private static ServerMessage handleSessionInit(
final Server.Context context,
private static ServerMessage handleSessionInit (
final SessionInitRequest request,
final Server.Context context,
final ServerMessage.Builder builder
) throws RequestErrorException
final Session session = context.sessionManager.createSession();
) throws RequestErrorException {
final Session session = context.sessionManager.createSession ();
// Client requires the ShadowVM functionality
if (request.getRequireShvm()) {
final boolean analysisRequired = request.getRequireShvm();
session.setShadowVMRequested (analysisRequired);
if (analysisRequired) {
// Server is able to provide such functionality
if (context.isShvm) {
session.setShadowVM(new SHVMImpl(context.log));
session.setShadowVM (new SHVMImpl (context.log));
} else {"Client requested unsupported functionality (analysis). "
+ "To enable it, run the server with the --analysis option.");
throw new RequestErrorException("Server does not provide analysis services");
} (
"Client requested analysis functionality. "+
"To enable it, run the server with the --analysis option."
throw new RequestErrorException (
"Server does not provide analysis services"
// Client requires the DiSL functionality
if (request.getRequireDisl() && !context.isDisl) {"Client requested unsupported functionality (instrumentation). "
+ "To enable it, run the server with the --instrumentation option.");
throw new RequestErrorException("Server does not provide instrumentation services");
final boolean instrumentationRequired = request.getRequireDisl();
session.setDiSLRequested (instrumentationRequired);
if (instrumentationRequired && !context.isDisl) {
"Client requested instrumentation functionality. "+
"To enable it, run the server with the --instrumentation option."
throw new RequestErrorException (
"Server does not provide instrumentation services"
return builder
return builder.setSessionInitResponse (
SessionInitResponse.newBuilder ().setSessionId ( ()).build ()
).build ();
......@@ -138,35 +147,18 @@ final class RequestDispatcher {
* Handles the request to close the session. Requests the session manager to
* terminate the session and remove it from its registry.
* Note that the instances in {@link Server.Context} might be null, when the functionality is
* not required by the client.
* @param context
* @param sessionId
* @return
* @throws RequestErrorException
* @param context
private static ServerMessage handleCloseConnection (
final Server.Context context, final int sessionId
private static void handleCloseConnection (
final int sessionId, final Server.Context context
) throws RequestErrorException {
context.log.debug ("Closing session %d", sessionId);
context.log.debug ("closing session %d", sessionId);
context.sessionManager.terminateSession (sessionId);
return null;
* Create the protobuf error message that will be sent to the client in case of failure or
* wrong request.
* @param message The message text.
* @return Error message that will be sent to the client.
private static Main.Error __createErrorMessage(final String message)
return Main.Error.newBuilder()
private RequestDispatcher () { /* No instances to be made. */ }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment