package org.nd4j.aeron.ipc; /* * Copyright 2014 - 2016 Real Logic Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ import io.aeron.Image; import io.aeron.Subscription; import io.aeron.driver.MediaDriver; import io.aeron.driver.ThreadingMode; import io.aeron.logbuffer.FragmentHandler; import io.aeron.protocol.HeaderFlyweight; import org.agrona.BitUtil; import org.agrona.LangUtil; import org.agrona.concurrent.BusySpinIdleStrategy; import org.agrona.concurrent.IdleStrategy; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; /** * Utility functions for samples */ public class AeronUtil { /** * Get a media driver context * for sending ndarrays * based on a given length * where length is the length (number of elements) * in the ndarrays hat are being sent * @param length the length to based the ipc length * @return the media driver context based on the given length */ public static MediaDriver.Context getMediaDriverContext(int length) { //length of array * sizeof(float) int ipcLength = length * 16; //padding for NDArrayMessage ipcLength += 64; //must be a power of 2 ipcLength *= 2; //ipc length must be positive power of 2 while (!BitUtil.isPowerOfTwo(ipcLength)) ipcLength += 2; // System.setProperty("aeron.term.buffer.size",String.valueOf(ipcLength)); final MediaDriver.Context ctx = new MediaDriver.Context().threadingMode(ThreadingMode.SHARED).dirsDeleteOnStart(true) /* .ipcTermBufferLength(ipcLength) .publicationTermBufferLength(ipcLength) .maxTermBufferLength(ipcLength)*/ .conductorIdleStrategy(new BusySpinIdleStrategy()) .receiverIdleStrategy(new BusySpinIdleStrategy()) .senderIdleStrategy(new BusySpinIdleStrategy()); return ctx; } /** * Aeron channel generation * @param host the host * @param port the port * @return the aeron channel via udp */ public static String aeronChannel(String host, int port) { return String.format("aeron:udp?endpoint=%s:%d", host, port); } /** * Return a reusable, parametrized * event loop that calls a * default idler * when no messages are received * * @param fragmentHandler to be called back for each message. * @param limit passed to {@link Subscription#poll(FragmentHandler, int)} * @param running indication for loop * @return loop function */ public static Consumer<Subscription> subscriberLoop(final FragmentHandler fragmentHandler, final int limit, final AtomicBoolean running, final AtomicBoolean launched) { final IdleStrategy idleStrategy = new BusySpinIdleStrategy(); return subscriberLoop(fragmentHandler, limit, running, idleStrategy, launched); } /** * Return a reusable, parameterized event * loop that calls and idler * when no messages are received * * @param fragmentHandler to be called back for each message. * @param limit passed to {@link Subscription#poll(FragmentHandler, int)} * @param running indication for loop * @param idleStrategy to use for loop * @return loop function */ public static Consumer<Subscription> subscriberLoop(final FragmentHandler fragmentHandler, final int limit, final AtomicBoolean running, final IdleStrategy idleStrategy, final AtomicBoolean launched) { return (subscription) -> { try { while (running.get()) { idleStrategy.idle(subscription.poll(fragmentHandler, limit)); launched.set(true); } } catch (final Exception ex) { LangUtil.rethrowUnchecked(ex); } }; } /** * Return a reusable, parameterized {@link FragmentHandler} that prints to stdout * * @param streamId to show when printing * @return subscription data handler function that prints the message contents */ public static FragmentHandler printStringMessage(final int streamId) { return (buffer, offset, length, header) -> { final byte[] data = new byte[length]; buffer.getBytes(offset, data); System.out.println(String.format("Message to stream %d from session %d (%d@%d) <<%s>>", streamId, header.sessionId(), length, offset, new String(data))); }; } /** * Generic error handler that just prints message to stdout. * * @param channel for the error * @param streamId for the error * @param sessionId for the error, if source * @param message indicating what the error was * @param cause of the error */ public static void printError(final String channel, final int streamId, final int sessionId, final String message, final HeaderFlyweight cause) { System.out.println(message); } /** * Print the rates to stdout * * @param messagesPerSec being reported * @param bytesPerSec being reported * @param totalMessages being reported * @param totalBytes being reported */ public static void printRate(final double messagesPerSec, final double bytesPerSec, final long totalMessages, final long totalBytes) { System.out.println(String.format("%.02g msgs/sec, %.02g bytes/sec, totals %d messages %d MB", messagesPerSec, bytesPerSec, totalMessages, totalBytes / (1024 * 1024))); } /** * Print the information for an available image to stdout. * * @param image that has been created */ public static void printAvailableImage(final Image image) { final Subscription subscription = image.subscription(); System.out.println(String.format("Available image on %s streamId=%d sessionId=%d from %s", subscription.channel(), subscription.streamId(), image.sessionId(), image.sourceIdentity())); } /** * Print the information for an unavailable image to stdout. * * @param image that has gone inactive */ public static void printUnavailableImage(final Image image) { final Subscription subscription = image.subscription(); System.out.println(String.format("Unavailable image on %s streamId=%d sessionId=%d", subscription.channel(), subscription.streamId(), image.sessionId())); } }