// Copyright © 2011-2014, Esko Luontola <www.orfjackal.net> // This software is released under the Apache License 2.0. // The license text is at http://www.apache.org/licenses/LICENSE-2.0 package fi.jumi.core.ipc; import com.google.common.util.concurrent.SettableFuture; import fi.jumi.core.config.SuiteConfiguration; import fi.jumi.core.events.RequestListenerEventizer; import fi.jumi.core.ipc.api.*; import fi.jumi.core.ipc.channel.*; import fi.jumi.core.ipc.dirs.CommandDir; import fi.jumi.core.ipc.encoding.*; import javax.annotation.concurrent.NotThreadSafe; import java.io.Closeable; import java.nio.file.Path; import java.util.concurrent.*; @NotThreadSafe public class IpcCommandSender implements Closeable { private final IpcWriter<RequestListener> requestWriter; private final RequestListener requestSender; private final BlockingQueue<ResponseListener> handlersForExpectedResponses = new LinkedBlockingQueue<>(); public IpcCommandSender(CommandDir commandDir, Executor workerThreads) { this.requestWriter = IpcChannel.writer(commandDir.getRequestPath(), RequestListenerEncoding::new); this.requestSender = new RequestListenerEventizer().newFrontend(requestWriter); workerThreads.execute(new ResponseReader(commandDir, handlersForExpectedResponses)); } @Override public void close() { requestWriter.close(); } public Future<Path> runTests(SuiteConfiguration suiteConfiguration) { SettableFuture<Path> future = SettableFuture.create(); handlersForExpectedResponses.add(new ResponseListener() { @Override public void onSuiteStarted(Path suiteResults) { future.set(suiteResults); } }); requestSender.runTests(suiteConfiguration); return future; } public void shutdown() { requestSender.shutdown(); } @NotThreadSafe private static class ResponseReader implements Runnable { private final CommandDir commandDir; private final BlockingQueue<ResponseListener> handlersForExpectedResponses; public ResponseReader(CommandDir commandDir, BlockingQueue<ResponseListener> handlersForExpectedResponses) { this.commandDir = commandDir; this.handlersForExpectedResponses = handlersForExpectedResponses; } @Override public void run() { IpcReader<ResponseListener> responseReader = IpcChannel.reader(commandDir.getResponsePath(), ResponseListenerEncoding::new); ResponseListener responseHandler = new ResponseListener() { @Override public void onSuiteStarted(Path suiteResults) { ResponseListener handler = handlersForExpectedResponses.poll(); if (handler == null) { throw new IllegalStateException("Nobody was expecting this event"); } handler.onSuiteStarted(suiteResults); } }; try { IpcReaders.decodeAll(responseReader, responseHandler); } catch (InterruptedException e) { System.err.println(this + " interrupted"); Thread.currentThread().interrupt(); } } } }