use of alma.benchmark.NcEventSpec in project ACS by ACS-Community.
the class CorbaNotifyConsumerImpl method receiveEvents.
@Override
public int receiveEvents(NcEventSpec[] ncEventSpecs, int processingDelayMillis, int numberOfEvents) throws CouldntPerformActionEx {
if (receiveMethodCalled.getAndSet(true)) {
AcsJCouldntPerformActionEx ex = new AcsJCouldntPerformActionEx("Method receiveEvents can be called only once during the component lifecycle.");
throw ex.toCouldntPerformActionEx();
}
if (cancel) {
AcsJCouldntPerformActionEx ex = new AcsJCouldntPerformActionEx("Method receiveEvents cannot be called after interrupt / ncDisconnect.");
throw ex.toCouldntPerformActionEx();
}
m_logger.info("Will receive events on " + ncEventSpecs.length + " NC(s), with processingDelayMillis=" + processingDelayMillis + ", numberOfEvents=" + (numberOfEvents > 0 ? numberOfEvents : "infinite"));
// sync object used to wait for numberOfEvents (if specified)
if (numberOfEvents > 0) {
sharedEventCountdown = new CountDownLatch(numberOfEvents);
}
StopWatch sw = new StopWatch();
try {
// iterate over NCs
for (NcEventSpec ncEventSpec : ncEventSpecs) {
AcsEventSubscriber<IDLEntity> sub = subsOrPubs.get(ncEventSpec.ncName);
if (sub == null) {
throw new AcsJCouldntPerformActionEx("No subscriber available for NC '" + ncEventSpec.ncName + "'.");
}
// iterate over event types
for (String eventName : ncEventSpec.eventNames) {
sub.addSubscription(createEventHandler(eventName, ncEventSpec.antennaName, processingDelayMillis));
m_logger.info("Added subscription for event=" + eventName + ", NC=" + ncEventSpec.ncName);
}
sub.startReceivingEvents();
}
} catch (AcsJCouldntPerformActionEx ex) {
ex.printStackTrace();
throw ex.toCouldntPerformActionEx();
} catch (Exception ex) {
ex.printStackTrace();
throw new AcsJCouldntPerformActionEx(ex).toCouldntPerformActionEx();
}
m_logger.info(ncEventSpecs.length + " subscriber(s) set up to receive events, which took " + sw.getLapTimeMillis() + " ms.");
if (numberOfEvents > 0) {
m_logger.info("Will wait for a total of " + numberOfEvents + " events to be received, with timeout after 10 minutes.");
try {
boolean cleanTermination = sharedEventCountdown.await(10, TimeUnit.MINUTES);
if (cleanTermination) {
m_logger.info("Received the expected " + numberOfEvents + " events in " + sw.getLapTimeMillis() + " ms.");
} else {
m_logger.warning("Unforeseen termination of event suppliers after 10 min (timeout).");
cancel = true;
}
} catch (InterruptedException ex) {
cancel = true;
}
} else {
m_logger.info("Will return from receiveEvents now but will keep receiving events.");
}
if (cancel) {
throw new AcsJCouldntPerformActionEx("Event receiving was interrupted or failed otherwise.").toCouldntPerformActionEx();
} else {
long receptionTimeNanos = (numberOfEvents > 0 && firstEventReceivedTimeNanos.longValue() > 0 ? (System.nanoTime() - firstEventReceivedTimeNanos.longValue()) : -1);
return (int) TimeUnit.NANOSECONDS.toMillis(receptionTimeNanos);
}
}
use of alma.benchmark.NcEventSpec in project ACS by ACS-Community.
the class LocalPubSubTest method testOneSupplierNoSubscriber.
/**
* Publishes 10.000 "MountStatusData" events on the NC "CONTROL_REALTIME",
* using a single supplier component "JavaSupplier-1" for sequential publishing at maximum rate.
* The call to the supplier component is synchronous, returning when all events are published.
* This allows us to measure the the publishing performance without sync'ing up through a subscriber.
*/
@Test
public void testOneSupplierNoSubscriber() throws Exception {
final int numEvents = 10000;
CorbaNotifySupplierOperations supplierComp = null;
try {
// Create dynamic supplier component
String componentName = "JavaSupplier-1";
supplierComp = componentAccessUtil.getDynamicSupplierComponent(componentName, supplierContainerName, ImplLangT.JAVA);
// supplier setup
String[] ncNames = new String[] { CHANNELNAME_CONTROL_REALTIME.value };
supplierComp.ncConnect(ncNames);
m_logger.info("Connected to NC " + ncNames[0]);
NcEventSpec[] ncEventSpecs = new NcEventSpec[] { new NcEventSpec(ncNames[0], new String[] { "MountStatusData" }, // don't care about antenna name here
"") };
// Let publisher component publish these events
int callTimeInternalMillis = supplierComp.sendEvents(ncEventSpecs, -1, numEvents);
m_logger.info("Single supplier comp '" + componentName + "' sent " + numEvents + " MountStatusData events at max speed to NC '" + ncNames[0] + "' in " + callTimeInternalMillis + " ms.");
assertThat("Expecting at most 4 ms for publishing an event to a NotifyService.", callTimeInternalMillis, lessThanOrEqualTo(numEvents * 4));
} finally {
// clean up
if (supplierComp != null)
supplierComp.ncDisconnect();
if (componentAccessUtil != null)
componentAccessUtil.releaseAllComponents(true);
}
}
use of alma.benchmark.NcEventSpec in project ACS by ACS-Community.
the class PubSubExecutor method execute.
/**
* Run the specified pub/sub container and components.
* If this method gets called directly (and not by {@link #execute(PubSubScenario)},
* the executionTime parameter can overwrite the timeout setting from the XML, or can
* set a timeout complementary to a finite <code>PubSubSpecCommonT#numberOfEvents</code>.
*/
public void execute(PubSubScenario scenario, long executionTimeMax, TimeUnit executionTimeMaxUnit) throws Throwable {
PubSubInfrastructureSpec pubSubSpec = scenario.getSpec();
m_logger.info("Will execute test with description:\n" + pubSubSpec.getTestDescription());
SimpleLoggingSpecT loggingSpec = (pubSubSpec.getLogging() != null ? pubSubSpec.getLogging() : defaultLoggingSpec);
AcsLogLevelDefinition levelDefaultLocal = AcsLogLevelDefinition.fromInteger(loggingSpec.getDefaultLevelMinLocal());
AcsLogLevelDefinition levelDefault = AcsLogLevelDefinition.fromInteger(loggingSpec.getDefaultLevelMin());
AcsLogLevelDefinition levelJacORB = AcsLogLevelDefinition.fromInteger(loggingSpec.getJacorbLevelMin());
List<Throwable> errors = new ArrayList<Throwable>();
try {
for (ContainerSpecT containerSpec : pubSubSpec.getContainer()) {
// start containers sequentially (TODO: with thread pool)
String host = (containerSpec.getHostName() != null ? containerSpec.getHostName() : localhostName);
String containerName = containerSpec.getContainerName();
m_logger.fine("about to start container " + containerName + " on host " + (host == null ? "localhost" : host));
ContainerImplLangType implLang = ContainerImplLangType.valueOf(containerSpec.getImplLang().toString());
containerUtil.startContainer(host, implLang, containerName, null, true);
// configure container log levels
ContainerLogLevelSpec contLogLevelSpec = new ContainerLogLevelSpec(levelDefault, levelDefaultLocal);
contLogLevelSpec.addNamedLoggerSpec("jacorb@" + containerName, levelJacORB, levelJacORB);
containerUtil.setContainerLogLevels(containerName, contLogLevelSpec);
m_logger.info("started container " + containerName + " on host " + (host == null ? "localhost" : host));
}
} catch (Throwable thr) {
errors.add(thr);
}
boolean allPubSubHaveFiniteEvents = true;
ExecutorService pubSubExec = Executors.newCachedThreadPool(getContainerServices().getThreadFactory());
if (errors.isEmpty()) {
for (final SubscriberSpecT subSpec : pubSubSpec.getSubscriber()) {
boolean subIsBlocking = isBlocking(subSpec);
if (!subIsBlocking) {
allPubSubHaveFiniteEvents = false;
}
ImplLangT implLang = deriveComponentImplLang(subSpec, pubSubSpec);
// TODO: pack this into one call, now that the comp will fail on the second call !!!
if (componentAccessUtil.getCachedComponentNames().contains(subSpec.getComponentName())) {
m_logger.info("Multiple subscribers specified for component " + subSpec.getComponentName() + ". This is legal, but unusual. Some values may be overwritten.");
}
CorbaNotifyConsumerOperations subscriberComp = componentAccessUtil.getDynamicSubscriberComponent(subSpec.getComponentName(), subSpec.getContainerName(), implLang);
if (subSpec.hasLogMultiplesOfEventCount()) {
subscriberComp.setEventLogging(subSpec.getLogMultiplesOfEventCount());
}
PubSubRunner runner = new PubSubRunner(subSpec, subscriberComp, pubSubExec, m_logger) {
@Override
protected Integer callSpecific(NcEventSpec eventSpec, int numEvents) throws CouldntPerformActionEx {
logger.info("About to call subscriber#receiveEvents...");
int processingDelay = (subSpec.hasProcessingDelayMillis() ? subSpec.getProcessingDelayMillis() : -1);
return ((CorbaNotifyConsumerOperations) pubSubComp).receiveEvents(new NcEventSpec[] { eventSpec }, processingDelay, numEvents);
}
};
try {
runner.runPubSub();
} catch (Exception ex) {
errors.add(ex);
}
}
// to "ensure" that even the asynchronously called subscribers are ready before we publish events
Thread.sleep(100);
for (final PublisherSpecT pubSpec : pubSubSpec.getPublisher()) {
boolean pubIsBlocking = isBlocking(pubSpec);
if (!pubIsBlocking) {
allPubSubHaveFiniteEvents = false;
}
ImplLangT implLang = deriveComponentImplLang(pubSpec, pubSubSpec);
// (which will result in multiple NCPublisher instances created by that component).
if (componentAccessUtil.getCachedComponentNames().contains(pubSpec.getComponentName())) {
m_logger.info("Multiple publishers specified for component " + pubSpec.getComponentName() + ". This is legal, but unusual. Some values may be overwritten.");
}
CorbaNotifySupplierOperations publisherComp = componentAccessUtil.getDynamicSupplierComponent(pubSpec.getComponentName(), pubSpec.getContainerName(), implLang);
if (pubSpec.hasLogMultiplesOfEventCount()) {
publisherComp.setEventLogging(pubSpec.getLogMultiplesOfEventCount());
}
PubSubRunner runner = new PubSubRunner(pubSpec, publisherComp, pubSubExec, m_logger) {
@Override
protected Integer callSpecific(NcEventSpec eventSpec, int numEvents) throws CouldntPerformActionEx {
logger.info("About to call publisher#sendEvents...");
int eventPeriodMillis = (pubSpec.hasEventPeriodMillis() ? pubSpec.getEventPeriodMillis() : -1);
return ((CorbaNotifySupplierOperations) pubSubComp).sendEvents(new NcEventSpec[] { eventSpec }, eventPeriodMillis, numEvents);
}
};
try {
runner.runPubSub();
} catch (Exception ex) {
errors.add(ex);
}
}
}
// wait for NC scenario to execute
if (errors.isEmpty()) {
if (allPubSubHaveFiniteEvents) {
// wait for all suppliers and subscribers to finish, enforcing the timeout if applicable
// TODO: More options would be available if we stored the PubSubRunner instances in a list...
pubSubExec.shutdown();
if (executionTimeMax > 0) {
pubSubExec.awaitTermination(executionTimeMax, executionTimeMaxUnit);
} else {
// like Dornroeschen
pubSubExec.awaitTermination(100 * 365, TimeUnit.DAYS);
}
} else {
// even if some others should terminate by themselves
if (executionTimeMax > 0) {
try {
m_logger.info("Will sleep for " + executionTimeMax + " " + executionTimeMaxUnit.toString().toLowerCase() + "...");
executionTimeMaxUnit.sleep(executionTimeMax);
} catch (Exception ex) {
errors.add(ex);
}
// now also the finite suppliers/subscribers should be finished, but even if not they will get interrupted
// along with the infinite ones in the cleanup.
} else {
errors.add(new IllegalArgumentException("An execution time must be specified if some publisher or subscriber is configured with an infinite number of events. Terminating right away..."));
}
}
}
// cleanup
m_logger.info("Will clean up the pub/sub components...");
// interrupt and release all components
for (ACSComponentOperations comp : componentAccessUtil.getCachedComponents()) {
// we could avoid the casting if we keep a separate list of subscriber and supplier comps...
if (comp instanceof CorbaNotifyCompBaseOperations) {
CorbaNotifyCompBaseOperations pubSubComp = (CorbaNotifyCompBaseOperations) comp;
pubSubComp.ncDisconnect();
}
}
componentAccessUtil.releaseAllComponents(true);
// stop containers
for (ContainerSpecT containerSpec : pubSubSpec.getContainer()) {
try {
String host = (containerSpec.getHostName() != null ? containerSpec.getHostName() : localhostName);
String containerName = containerSpec.getContainerName();
m_logger.fine("about to stop container " + containerName + " on host " + (host == null ? "localhost" : host));
containerUtil.stopContainer(host, containerName);
m_logger.info("stopped container " + containerName + " on host " + (host == null ? "localhost" : host));
} catch (Throwable thr) {
errors.add(thr);
}
}
if (!errors.isEmpty()) {
m_logger.severe("There were " + errors.size() + " errors!");
throw errors.get(0);
}
}
use of alma.benchmark.NcEventSpec in project ACS by ACS-Community.
the class CorbaNotifySupplierImpl method sendEvents.
@Override
public int sendEvents(NcEventSpec[] ncEventSpecs, int eventPeriodMillis, int numberOfEvents) throws CouldntPerformActionEx {
if (cancel) {
AcsJCouldntPerformActionEx ex = new AcsJCouldntPerformActionEx("Method sendEvents cannot be called after interrupt / ncDisconnect.");
throw ex.toCouldntPerformActionEx();
}
StopWatch sw = null;
ScheduledThreadPoolExecutor runner = null;
// Set up the runnables for all NCs
try {
for (NcEventSpec ncEventSpec : ncEventSpecs) {
PublishEventRunnable runnable = new PublishEventRunnable(ncEventSpec, this.subsOrPubs.get(ncEventSpec.ncName), numberOfEvents);
runnables.add(runnable);
}
// multithreaded executor
runner = new ScheduledThreadPoolExecutor(// thread per NC
ncEventSpecs.length, m_containerServices.getThreadFactory(), //RejectedExecutionException
new AbortPolicy());
sw = new StopWatch();
// run the NC suppliers
for (PublishEventRunnable runnable : runnables) {
ScheduledFuture<?> future = null;
if (eventPeriodMillis > 0) {
// publish at fixed rate
future = runner.scheduleAtFixedRate(runnable, 0, eventPeriodMillis, TimeUnit.MILLISECONDS);
} else {
// run continuously
// delay must be > 0, otherwise IllegalArgumentException
future = runner.scheduleWithFixedDelay(runnable, 0, 1, TimeUnit.NANOSECONDS);
}
runnable.setScheduledFuture(future);
}
} catch (Exception ex) {
m_logger.log(AcsLogLevel.SEVERE, "sendEvents call failed", ex);
throw new AcsJCouldntPerformActionEx(ex).toCouldntPerformActionEx();
}
String msgBase = "Started publishing events on " + ncEventSpecs.length + " NC(s), sending events " + (eventPeriodMillis > 0 ? "every " + eventPeriodMillis + " ms. " : "as fast as possible. ");
if (numberOfEvents > 0) {
m_logger.info(msgBase + "Will now wait until " + numberOfEvents + " have been published on every NC...");
// block until all events are sent
runner.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
runner.setExecuteExistingDelayedTasksAfterShutdownPolicy(true);
runner.shutdown();
try {
// 10 min timeout, just to clean up resources eventually.
// TODO: Offer a workaround for special long-running tests
boolean cleanTermination = runner.awaitTermination(10, TimeUnit.MINUTES);
if (!cleanTermination) {
m_logger.warning("Unforeseen termination of event suppliers after 10 min (timeout).");
cancel = true;
}
} catch (InterruptedException ex) {
cancel = true;
}
} else {
runnersToInterrupt.add(runner);
m_logger.info(msgBase + "Will return and asynchronously continue publishing events, until interrupt() gets called.");
}
if (cancel) {
throw new AcsJCouldntPerformActionEx("Event sending was interrupted or failed otherwise.").toCouldntPerformActionEx();
}
return (int) sw.getLapTimeMillis();
}
use of alma.benchmark.NcEventSpec in project ACS by ACS-Community.
the class LocalPubSubTest method testOneSupplierOneSubscriberMixedEvents.
/**
* Publishes >= 200 "MountStatusData" or "LightweightMountStatusData" events on the NC "CONTROL_REALTIME",
* using a single supplier component "JavaSupplier-1" for sequential publishing at a rate of 1 events every 48 ms,
* and a single subscriber component "JavaSubscriber" for counting the events.
* The call to the supplier component is asynchronous, returning while the publisher runs in "indefinite publishing" mode.
* Once the subscriber has received enough data, we terminate the supplier.
*/
@Test
public void testOneSupplierOneSubscriberMixedEvents() throws Throwable {
final int numEvents = 200;
final int eventPeriodMillis = 48;
String[] ncNames = new String[] { CHANNELNAME_CONTROL_REALTIME.value };
// mixed events spec
final NcEventSpec[] ncEventSpecs = new NcEventSpec[] { new NcEventSpec(ncNames[0], new String[] { "MountStatusData", "LightweightMountStatusData" }, // don't care about antenna name here
"") };
// Create, configure and activate dynamic subscriber component.
// It must be running before we publish events, to make sure we don't lose any.
String subscriberContainerName = "localSubscriberContainer1";
String subscriberComponentName = "JavaSubscriber-1";
try {
containerUtil.startContainer(localhostName, ContainerImplLangType.JAVA, subscriberContainerName, null, true);
final CorbaNotifyConsumerOperations subscriberComp = componentAccessUtil.getDynamicSubscriberComponent(subscriberComponentName, subscriberContainerName, ImplLangT.JAVA);
subscriberComp.ncConnect(ncNames);
m_logger.info("Connected subscriber to NC " + ncNames[0]);
Callable<Integer> runSubscriber = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
m_logger.info("About to call subscriber#receiveEvents in a separate thread...");
return subscriberComp.receiveEvents(ncEventSpecs, 0, numEvents);
}
};
Future<Integer> subscriberCallFuture = singThrExec.submit(runSubscriber);
// to "ensure" that the subscriber is ready before we publish events
Thread.sleep(100);
// Create dynamic supplier component
String componentName = "JavaSupplier-1";
CorbaNotifySupplierOperations supplierComp = componentAccessUtil.getDynamicSupplierComponent(componentName, supplierContainerName, ImplLangT.JAVA);
// supplier setup
supplierComp.ncConnect(ncNames);
m_logger.info("Connected supplier to NC " + ncNames[0] + ". Will now send ~" + numEvents + " events, one every " + eventPeriodMillis + " ms.");
// Let publisher component publish events as long as it takes for the subscriber to get enough of them
supplierComp.sendEvents(ncEventSpecs, eventPeriodMillis, -1);
int subscriberReceptionTimeMillis = subscriberCallFuture.get(60, TimeUnit.SECONDS);
m_logger.info("Subscriber component done. It received " + numEvents + " events in " + subscriberReceptionTimeMillis + " ms.");
int expectedReceptionTimeMillis = numEvents * eventPeriodMillis;
assertThat("It should have taken around " + expectedReceptionTimeMillis + " ms to receive the events.", subscriberReceptionTimeMillis, is(both(greaterThan((int) (0.90 * expectedReceptionTimeMillis))).and(lessThan((int) (1.1 * expectedReceptionTimeMillis)))));
// stop supplier (it was in 'infinite' sending mode)
supplierComp.interrupt();
} catch (CouldntPerformActionEx ex) {
throw AcsJCouldntPerformActionEx.fromCouldntPerformActionEx(ex);
} catch (ExecutionException ex) {
Throwable ex2 = ex.getCause();
if (ex2 instanceof CouldntPerformActionEx) {
throw AcsJCouldntPerformActionEx.fromCouldntPerformActionEx((CouldntPerformActionEx) ex2);
} else {
throw ex2;
}
} finally {
componentAccessUtil.releaseComponent(subscriberComponentName, true);
containerUtil.stopContainer(localhostName, subscriberContainerName);
// for supplier component and container we trust the tearDown method..
}
}
Aggregations