Search in sources :

Example 1 with AcsEventSubscriber

use of alma.acs.nc.AcsEventSubscriber in project ACS by ACS-Community.

the class NCSubscriberAdminReuseTest method testNewAndOldNCsTogether.

/**
	 * TODO: Write a similar test with an old-style C++ Consumer, 
	 *       once we remove the deprecated Java NC Consumer.
	 */
public void testNewAndOldNCsTogether() throws Exception {
    List<Consumer> consumers = new ArrayList<Consumer>();
    for (int i = 1; i <= 10; i++) {
        // Create the maximum number of proxies per admin
        // Also, per every NCSubscriber, create an old Consumer
        AcsEventSubscriber[] subscribers = new AcsEventSubscriber[NCSubscriber.PROXIES_PER_ADMIN];
        for (int j = 0; j != NCSubscriber.PROXIES_PER_ADMIN; j++) {
            subscribers[j] = getContainerServices().createNotificationChannelSubscriber(CHANNEL_NAME, IDLEntity.class);
            Consumer c = new Consumer(CHANNEL_NAME, getContainerServices());
            consumers.add(c);
        }
        assertEquals(i * (1 + NCSubscriber.PROXIES_PER_ADMIN), channel.get_all_consumeradmins().length);
    }
    // Now, let's examine the consumer admins, and see whether they are shared or not
    int sharedAdmins = 0;
    int lonelyAdmins = 0;
    for (int adminID : channel.get_all_consumeradmins()) {
        ConsumerAdmin admin = channel.get_consumeradmin(adminID);
        boolean isSharedAdmin = false;
        for (int proxyID : admin.push_suppliers()) {
            ProxySupplier proxy = admin.get_proxy_supplier(proxyID);
            if (ProxyType.PUSH_ANY.equals(proxy.MyType())) {
                isSharedAdmin = true;
                break;
            }
        }
        if (isSharedAdmin) {
            assertEquals(NCSubscriber.PROXIES_PER_ADMIN, admin.push_suppliers().length - 1);
            sharedAdmins++;
        } else
            lonelyAdmins++;
    }
    assertEquals(10, sharedAdmins);
    assertEquals(10 * NCSubscriber.PROXIES_PER_ADMIN, lonelyAdmins);
    // Manually free these old filthy consumers
    for (Consumer c : consumers) c.disconnect();
}
Also used : ConsumerAdmin(org.omg.CosNotifyChannelAdmin.ConsumerAdmin) AcsEventSubscriber(alma.acs.nc.AcsEventSubscriber) ArrayList(java.util.ArrayList) ProxySupplier(org.omg.CosNotifyChannelAdmin.ProxySupplier) IDLEntity(org.omg.CORBA.portable.IDLEntity)

Example 2 with AcsEventSubscriber

use of alma.acs.nc.AcsEventSubscriber in project ACS by ACS-Community.

the class InMemoryNcTest method testConcurrentUse.

/**
	 * Heavy-duty test to check for concurrency problems
	 * and to do basic verification of throughput performance (which is limited by having a single receiver).
	 * <p>
	 * We want to test also the asynchronous event processing in AcsEventSubscriberImplBase, 
	 * but then must throttle the publishers so that the subscribers don't lose data.
	 * Still we want the publishers to fire fast enough so that the subscribers get stressed at times.
	 * This is achieved by letting the publishers fire batches of events at maximum speed,
	 * but then wait for the entire batch to be received by the registered receiver class.
	 * These pulses of events are calculated to at most fill up the subscriber queue completely,
	 * which means that we may get warnings about slow receivers ("More events came in from the NC than the receiver processed"), 
	 * but still no data should be lost ("numEventsDiscarded=0").
	 */
@Test
public void testConcurrentUse() throws Exception {
    InMemoryNcFake nc = new InMemoryNcFake(services, "myTestChannel");
    final int numEventsPerPublisher = 2000;
    final int numPublishers = 5;
    final int numEventsPublishedTotal = numEventsPerPublisher * numPublishers;
    final int numActiveSubscribers = 5;
    final int numInactiveSubscribers = 2;
    final int numEventsToReceiveTotal = numEventsPublishedTotal * numActiveSubscribers;
    final int eventBatchSize = Math.min(numEventsPerPublisher, AcsEventSubscriberImplBase.EVENT_QUEUE_CAPACITY / numPublishers);
    assertThat("Current choice of test parameters leads to illegal batch size.", eventBatchSize, greaterThanOrEqualTo(1));
    final int numEventsToReceivePerBatch = eventBatchSize * numPublishers * numActiveSubscribers;
    logger.info("Will use " + numPublishers + " publishers to each publish " + numEventsPerPublisher + " events (in batches of " + eventBatchSize + " each synchronized with the receivers), and " + numActiveSubscribers + " subscribers for these events. In addition we have " + numInactiveSubscribers + " subscribers that should not receive these events.");
    StopWatch sw = new StopWatch(logger);
    // set up publishers (unlike above we do it before the subscribers, just to make sure that works as well)
    List<InMemoryPublisher<TestEventType1>> publishers = new ArrayList<InMemoryPublisher<TestEventType1>>(numPublishers);
    for (int i = 1; i <= numPublishers; i++) {
        AcsEventPublisher<TestEventType1> pub = nc.createPublisher("myTestPublisher" + i, TestEventType1.class);
        publishers.add((InMemoryPublisher) pub);
    }
    sw.logLapTime("create " + numPublishers + " publishers");
    // set up subscribers
    final SyncingEventCollector eventCollector = new SyncingEventCollector(numPublishers, numEventsToReceivePerBatch, numEventsToReceiveTotal);
    TestEventReceiver1 sharedReceiver = new TestEventReceiver1(eventCollector);
    List<AcsEventSubscriber<?>> subscribers = new ArrayList<AcsEventSubscriber<?>>(numActiveSubscribers);
    for (int i = 1; i <= numActiveSubscribers; i++) {
        AcsEventSubscriber<TestEventType1> sub = nc.createSubscriber("myTestSubscriber" + i, TestEventType1.class);
        subscribers.add(sub);
        sub.addSubscription(sharedReceiver);
        sub.startReceivingEvents();
    }
    for (int i = 1; i <= numInactiveSubscribers; i++) {
        if (i % 2 == 0) {
            AcsEventSubscriber<TestEventType1> sub = nc.createSubscriber("myInactiveTestSubscriber" + i, TestEventType1.class);
            subscribers.add(sub);
            sub.addSubscription(sharedReceiver);
        // do not call sub.startReceivingEvents() for this inactive subscriber
        } else {
            AcsEventSubscriber<TestEventType2> sub = nc.createSubscriber("myTestSubscriber" + i, TestEventType2.class);
            subscribers.add(sub);
            sub.startReceivingEvents();
        }
    }
    sw.logLapTime("create " + (numActiveSubscribers + numInactiveSubscribers) + " subscribers");
    // Publish and receive "event1" as specified above
    final TestEventType1 event1 = new TestEventType1();
    final List<Throwable> asyncThrowables = Collections.synchronizedList(new ArrayList<Throwable>());
    final CountDownLatch synchOnPublishers = new CountDownLatch(numPublishers);
    class PublisherRunnable implements Runnable {

        private final InMemoryPublisher<TestEventType1> publisher;

        PublisherRunnable(InMemoryPublisher<TestEventType1> publisher) {
            this.publisher = publisher;
        }

        @Override
        public void run() {
            for (int i = 1; i <= numEventsPerPublisher; i++) {
                try {
                    publisher.publishEvent(event1);
                    if (i % eventBatchSize == 0) {
                        awaitEventReception();
                    }
                } catch (Exception ex) {
                    asyncThrowables.add(ex);
                }
            }
            // test getEventCount()
            if (publisher.getEventCount() != numEventsPerPublisher) {
                asyncThrowables.add(new Exception("Published only " + publisher.getEventCount() + " events when " + numEventsPerPublisher + " were expected."));
            }
            try {
                publisher.disconnect();
            } catch (AcsJIllegalStateEventEx ex) {
                asyncThrowables.add(ex);
            }
            // the last batch may be smaller than eventBatchSize, so that we need to sync on their reception with this extra call
            awaitEventReception();
            synchOnPublishers.countDown();
        }

        private void awaitEventReception() {
            try {
                //					StopWatch swWait = new StopWatch(logger);
                eventCollector.awaitEventBatchReception();
            //					logger.fine("Publisher in thread " + Thread.currentThread().getName() + " returned from awaitEventBatchReception() in " + swWait.getLapTimeMillis() + " ms.");
            } catch (Exception ex) {
                asyncThrowables.add(ex);
            }
        }
    }
    // let each publisher fire its events from a separate thread
    for (InMemoryPublisher<TestEventType1> publisher : publishers) {
        services.getThreadFactory().newThread(new PublisherRunnable(publisher)).start();
    }
    // wait for publishers to fire all events (which includes already their waiting for event reception)
    assertThat(synchOnPublishers.await(1, TimeUnit.MINUTES), is(true));
    // verify results
    assertThat(asyncThrowables, is(empty()));
    assertThat(eventCollector.getNumEventsReceivedTotal(), equalTo((long) numEventsToReceiveTotal));
    sw.logLapTime("publish " + numEventsPublishedTotal + " and receive " + numEventsToReceiveTotal + " events");
}
Also used : ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) StopWatch(alma.acs.util.StopWatch) AcsEventSubscriber(alma.acs.nc.AcsEventSubscriber) AcsJIllegalStateEventEx(alma.ACSErrTypeCommon.wrappers.AcsJIllegalStateEventEx) Test(org.junit.Test)

Example 3 with AcsEventSubscriber

use of alma.acs.nc.AcsEventSubscriber in project ACS by ACS-Community.

the class ContainerServicesImpl method createNotificationChannelSubscriber.

/**
	 * @TODO: once we support notification over other frameworks, check that configuration 
	 * and instantiate some class other than NCSubscriber.
	 * @see alma.acs.container.ContainerServices#createNotificationChannelSubscriber(String, String)
	 */
@Override
public <T> AcsEventSubscriber<T> createNotificationChannelSubscriber(String channelName, String channelNotifyServiceDomainName, Class<T> eventType) throws AcsJContainerServicesEx {
    AcsEventSubscriber<T> subscriber = null;
    try {
        Object[] args = new Object[] { channelName, channelNotifyServiceDomainName, this, getNameService(), m_clientName, eventType };
        @SuppressWarnings("unchecked") Class<AcsEventSubscriber<T>> clazz = (Class<AcsEventSubscriber<T>>) Class.forName(CLASSNAME_NC_SUBSCRIBER);
        Constructor<AcsEventSubscriber<T>> constructor = clazz.getConstructor(String.class, String.class, ContainerServicesBase.class, NamingContext.class, String.class, Class.class);
        subscriber = constructor.newInstance(args);
    } catch (ClassNotFoundException e) {
        // TODO: maybe we could prevent future NCSubscriber creation tries, since the class isn't and will not be loaded
        //       The same applies for the next "catch" block
        m_logger.log(AcsLogLevel.ERROR, "Cannot create NC subscriber because the 'NCSubscriber' class is not present in the classpath", e);
        AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e);
        ex.setContextInfo("'" + CLASSNAME_NC_SUBSCRIBER + "' class not present in the classpath");
        throw ex;
    } catch (ClassCastException e) {
        m_logger.log(AcsLogLevel.ERROR, "Cannot create NC subscriber because loaded class is not of type 'AcsEventSubscriber", e);
        AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e);
        ex.setContextInfo("'" + CLASSNAME_NC_SUBSCRIBER + "' class does not extend 'AcsEventSubscriber'");
        throw ex;
    } catch (Throwable e) {
        if (e instanceof InvocationTargetException) {
            // ctor ex
            e = e.getCause();
        }
        m_logger.log(AcsLogLevel.ERROR, "Unexpected error while creating new AcsEventSubscriber object", e);
        AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e);
        throw ex;
    }
    m_subscribers.put((channelNotifyServiceDomainName == null ? "" : channelNotifyServiceDomainName) + "/" + channelName, subscriber);
    return subscriber;
}
Also used : AcsJContainerServicesEx(alma.JavaContainerError.wrappers.AcsJContainerServicesEx) InvocationTargetException(java.lang.reflect.InvocationTargetException) EntityT(alma.entities.commonentity.EntityT) AcsEventSubscriber(alma.acs.nc.AcsEventSubscriber)

Example 4 with AcsEventSubscriber

use of alma.acs.nc.AcsEventSubscriber in project ACS by ACS-Community.

the class NCSubscriberAdminReuseTest method runConcurrentSubscribersCreation.

private void runConcurrentSubscribersCreation(int numRealSubscribersDefinedTotal) throws Exception {
    m_logger.info("Setting up " + numRealSubscribersDefinedTotal + " concurrent subscriber creations...");
    final List<AcsEventSubscriber<IDLEntity>> subscribers = Collections.synchronizedList(new ArrayList<AcsEventSubscriber<IDLEntity>>());
    // Create all the tasks first
    ThreadBurstExecutorService executor = new ThreadBurstExecutorService(getContainerServices().getThreadFactory());
    for (int i = 0; i < numRealSubscribersDefinedTotal; i++) {
        Runnable r = new Runnable() {

            public void run() {
                try {
                    // create subscriber, and add it to the list
                    subscribers.add(getContainerServices().createNotificationChannelSubscriber(CHANNEL_NAME, IDLEntity.class));
                } catch (Exception e) {
                    m_logger.log(Level.WARNING, "Failed to create a subscriber.", e);
                }
            }
        };
        try {
            executor.submit(r, 100, TimeUnit.SECONDS);
        } catch (InterruptedException e1) {
            fail("Failed to submit the subscriber creator thread to the executor service");
        }
    }
    // and now run'em all at the same time! (concurrently)
    m_logger.info("Will run " + numRealSubscribersDefinedTotal + " concurrent subscriber creations...");
    try {
        boolean startOK = executor.executeAllAndWait(100, TimeUnit.SECONDS);
        assertTrue("Not all subscribers started within the alotted 100 seconds window.", startOK);
    } catch (InterruptedException e) {
        fail("Got InterruptedException while running all my threads");
    }
    // After all the show, we should have all requested subscribers in the local list
    assertEquals(numRealSubscribersDefinedTotal, subscribers.size());
    m_logger.info("Successfully created " + numRealSubscribersDefinedTotal + " subscribers semi-concurrently. Will now check their NC admin links...");
    // Check if these subscribers are distributed correctly over several admin objects,
    // allowing for some overbooking due to concurrent requests (see comment about concurrency in c'tor of NCSubscriber)
    final int allowedAdminOverbooking = 2;
    int numRealSubscribersFoundTotal = 0;
    int[] adminIDs = channel.get_all_consumeradmins();
    for (int i = 0; i < adminIDs.length; i++) {
        int adminID = adminIDs[i];
        String msgBase = "Subscriber admin #" + (i + 1) + " (of " + adminIDs.length + ") ";
        try {
            int subs = channel.get_consumeradmin(adminID).push_suppliers().length;
            // minus 1 for the 'management' subscriber
            int numRealSubscribersThisAdmin = subs - 1;
            m_logger.info(msgBase + "has " + numRealSubscribersThisAdmin + " proxy objects (subscribers) attached.");
            if (i < adminIDs.length - 1) {
                // This is not the last of the admin objects. It should be  filled to the brim with proxies.
                assertThat(msgBase + "should be full with " + NCSubscriber.PROXIES_PER_ADMIN + " proxies.", numRealSubscribersThisAdmin, greaterThanOrEqualTo(NCSubscriber.PROXIES_PER_ADMIN));
                assertThat(msgBase + "has more proxies than allowed by 'allowedAdminOverbooking'=" + allowedAdminOverbooking + ", which may be OK.", numRealSubscribersThisAdmin, lessThanOrEqualTo(NCSubscriber.PROXIES_PER_ADMIN + allowedAdminOverbooking));
            } else {
                // We should be at the last of the admin objects, which may be only partially filled
                assertThat(msgBase + "has more proxies than allowed by 'allowedAdminOverbooking'=" + allowedAdminOverbooking + ", which may be OK.", numRealSubscribersThisAdmin, lessThanOrEqualTo(NCSubscriber.PROXIES_PER_ADMIN + allowedAdminOverbooking));
                assertThat(msgBase + "should contain all remaining proxies.", numRealSubscribersThisAdmin, equalTo(numRealSubscribersDefinedTotal - numRealSubscribersFoundTotal));
            }
            numRealSubscribersFoundTotal += numRealSubscribersThisAdmin;
        } catch (AdminNotFound ex) {
            fail("Can't get information about consumer admin #" + (i + 1) + " (ID=" + adminID + "): " + ex.toString());
        }
    }
    destroyConsumers();
}
Also used : ThreadBurstExecutorService(alma.acs.concurrent.ThreadBurstExecutorService) AcsEventSubscriber(alma.acs.nc.AcsEventSubscriber) IDLEntity(org.omg.CORBA.portable.IDLEntity) AdminNotFound(org.omg.CosNotifyChannelAdmin.AdminNotFound)

Aggregations

AcsEventSubscriber (alma.acs.nc.AcsEventSubscriber)4 ArrayList (java.util.ArrayList)2 IDLEntity (org.omg.CORBA.portable.IDLEntity)2 AcsJIllegalStateEventEx (alma.ACSErrTypeCommon.wrappers.AcsJIllegalStateEventEx)1 AcsJContainerServicesEx (alma.JavaContainerError.wrappers.AcsJContainerServicesEx)1 ThreadBurstExecutorService (alma.acs.concurrent.ThreadBurstExecutorService)1 StopWatch (alma.acs.util.StopWatch)1 EntityT (alma.entities.commonentity.EntityT)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 Test (org.junit.Test)1 AdminNotFound (org.omg.CosNotifyChannelAdmin.AdminNotFound)1 ConsumerAdmin (org.omg.CosNotifyChannelAdmin.ConsumerAdmin)1 ProxySupplier (org.omg.CosNotifyChannelAdmin.ProxySupplier)1