Search in sources :

Example 21 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testSingleInstanceTwoMessagesSameClassCombinedExecution.

@Test
public void testSingleInstanceTwoMessagesSameClassCombinedExecution() throws Exception {
    final CombinedMP prototype = new CombinedMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<CombinedMP>(prototype))) {
        final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
        assertEquals("starts with no instances", 0, manager.getProcessorCount());
        final KeyedMessageWithType message1 = km(new MessageOne(123));
        final InstanceWrapper wrapper = manager.getInstanceForKey(message1.key, message1.message);
        manager.dispatch(message1, Operation.handle, true);
        assertEquals("instance was created", 1, manager.getProcessorCount());
        final KeyedMessageWithType message2 = km(new MessageOne(123));
        assertSame("same wrapper returned for second message", wrapper, manager.getInstanceForKey(message2.key, message2.message));
        manager.dispatch(message2, Operation.handle, true);
        final CombinedMP instance = (CombinedMP) wrapper.getInstance();
        assertEquals("no other instance was created", 1, manager.getProcessorCount());
        assertEquals("instance activated", 1, instance.activationCount);
        assertTrue("real activation time", instance.activationTime > 0);
        assertTrue("activated before first message", instance.activationTime < instance.firstMessageTime);
        assertEquals("both messages delivered", 2, instance.messages.size());
        assertSame("message1 delivered first", message1.message, instance.messages.get(0));
        assertSame("message2 delivered second", message2.message, instance.messages.get(1));
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 22 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testQueueIsClearedAfterExecution.

// This test no longer really matters since there is no queue but we might as well leave it
// since it exercises the container.
@Test
public void testQueueIsClearedAfterExecution() throws Exception {
    final CombinedMP prototype = new CombinedMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<CombinedMP>(prototype))) {
        final KeyedMessageWithType message = km(new MessageOne(123));
        final InstanceWrapper wrapper = manager.getInstanceForKey(message.key, message.message);
        manager.dispatch(message, Operation.handle, true);
        assertEquals("instance was created", 1, manager.getProcessorCount());
        final CombinedMP instance = (CombinedMP) wrapper.getInstance();
        assertEquals("instance activated", 1, instance.activationCount);
        assertTrue("real activation time", instance.activationTime > 0);
        assertSame("instance received message", message.message, instance.messages.get(0));
        assertEquals("message count", 1, instance.messages.size());
        assertTrue("activated before first message", instance.activationTime < instance.firstMessageTime);
        final long activationTime = instance.activationTime;
        final long firstMessageTime = instance.firstMessageTime;
        // here is where the queue would have been advanced again ... but there is no queue anymore.
        assertTrue("activation time didn't change", activationTime == instance.activationTime);
        assertTrue("message time didn't change", firstMessageTime == instance.firstMessageTime);
        assertEquals("message count didn't change", 1, instance.messages.size());
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 23 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class TestInstanceManager method testOutput.

@Test
public void testOutput() throws Exception {
    final OutputTestMP prototype = new OutputTestMP();
    try (final LockingContainer manager = setupContainer(new MessageProcessor<OutputTestMP>(prototype))) {
        final DummyDispatcher dispatcher = ((DummyDispatcher) manager.getDispatcher());
        // we need to dispatch messages to create MP instances
        final KeyedMessageWithType message1 = km(new MessageOne(1));
        final InstanceWrapper wrapper1 = manager.getInstanceForKey(message1.key, message1.message);
        manager.dispatch(message1, Operation.handle, true);
        final KeyedMessageWithType message2 = km(new MessageOne(2));
        final InstanceWrapper wrapper2 = manager.getInstanceForKey(message2.key, message2.message);
        manager.dispatch(message2, Operation.handle, true);
        assertEquals(new ReturnString("MessageOne"), dispatcher.lastDispatched.message);
        manager.outputPass();
        final OutputTestMP mp1 = (OutputTestMP) wrapper1.getInstance();
        assertTrue("MP1 output did not occur after activation", mp1.activationTime < mp1.outputTime);
        final OutputTestMP mp2 = (OutputTestMP) wrapper2.getInstance();
        assertTrue("MP2 output did not occur after activation", mp2.activationTime < mp2.outputTime);
        assertTrue(mp1 != mp2);
        assertEquals(new ReturnInt(42), dispatcher.lastDispatched.message);
    }
}
Also used : InstanceWrapper(net.dempsy.container.locking.LockingContainer.InstanceWrapper) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) Test(org.junit.Test)

Example 24 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class LockingContainer method dispatch.

// this is called directly from tests but shouldn't be accessed otherwise.
@Override
public void dispatch(final KeyedMessage message, final boolean block) throws IllegalArgumentException, ContainerException {
    if (!isRunningLazy) {
        LOGGER.debug("Dispacth called on stopped container");
        statCollector.messageFailed(false);
    }
    if (message == null)
        // No. We didn't process the null message
        return;
    if (!inbound.doesMessageKeyBelongToNode(message.key)) {
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Message with key " + SafeString.objectDescription(message.key) + " sent to wrong container. ");
        statCollector.messageFailed(false);
        return;
    }
    boolean evictedAndBlocking;
    if (message == null || message.message == null)
        throw new IllegalArgumentException("the container for " + clusterId + " attempted to dispatch null message.");
    if (message.key == null)
        throw new ContainerException("Message " + objectDescription(message.message) + " contains no key.");
    try {
        numBeingWorked.incrementAndGet();
        do {
            evictedAndBlocking = false;
            final InstanceWrapper wrapper = getInstanceForKey(message.key);
            // wrapper will be null if the activate returns 'false'
            if (wrapper != null) {
                final Object instance = wrapper.getExclusive(block);
                if (instance != null) {
                    // null indicates we didn't get the lock
                    final List<KeyedMessageWithType> response;
                    try {
                        if (wrapper.isEvicted()) {
                            response = null;
                            // a subsequent call to getInstanceForDispatch will create a new one.
                            if (block) {
                                Thread.yield();
                                // we're going to try again.
                                evictedAndBlocking = true;
                            } else {
                                // otherwise it's just like we couldn't get the lock. The Mp is busy being killed off.
                                if (LOGGER.isTraceEnabled())
                                    LOGGER.trace("the container for " + clusterId + " failed handle message due to evicted Mp " + SafeString.valueOf(prototype));
                                statCollector.messageCollision(message);
                            }
                        } else {
                            response = invokeOperation(wrapper.getInstance(), Operation.handle, message);
                        }
                    } finally {
                        wrapper.releaseLock();
                    }
                    if (response != null) {
                        try {
                            dispatcher.dispatch(response);
                        } catch (final Exception de) {
                            if (isRunning.get())
                                LOGGER.warn("Failed on subsequent dispatch of " + response + ": " + de.getLocalizedMessage());
                        }
                    }
                } else {
                    // ... we didn't get the lock
                    if (LOGGER.isTraceEnabled())
                        LOGGER.trace("the container for " + clusterId + " failed to obtain lock on " + SafeString.valueOf(prototype));
                    statCollector.messageCollision(message);
                }
            } else {
                // if we got here then the activate on the Mp explicitly returned 'false'
                if (LOGGER.isDebugEnabled())
                    LOGGER.debug("the container for " + clusterId + " failed to activate the Mp for " + SafeString.valueOf(prototype));
                // leave the do/while loop
                break;
            }
        } while (evictedAndBlocking);
    } finally {
        numBeingWorked.decrementAndGet();
    }
}
Also used : KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType) ContainerException(net.dempsy.container.ContainerException) ContainerException(net.dempsy.container.ContainerException) DempsyException(net.dempsy.DempsyException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException)

Example 25 with KeyedMessageWithType

use of net.dempsy.messages.KeyedMessageWithType in project Dempsy by Dempsy.

the class NonLockingContainer method outputPass.

// TODO: Output concurrency blocks normal message handling. Need a means of managing this better.
// This method MUST NOT THROW
@Override
protected void outputPass() {
    if (!prototype.isOutputSupported())
        return;
    // take a snapshot of the current container state.
    final LinkedList<Object> toOutput = new LinkedList<Object>(instances.keySet());
    Executor executorService = null;
    Semaphore taskLock = null;
    executorService = super.getOutputExecutorService();
    if (executorService != null)
        taskLock = new Semaphore(outputConcurrency);
    // This keeps track of the number of concurrently running
    // output tasks so that this method can wait until they're
    // all done to return.
    // 
    // It's also used as a condition variable signaling on its
    // own state changes.
    final AtomicLong numExecutingOutputs = new AtomicLong(0);
    // keep going until all of the outputs have been invoked
    while (toOutput.size() > 0 && isRunning.get()) {
        for (final Iterator<Object> iter = toOutput.iterator(); iter.hasNext(); ) {
            final Object key = iter.next();
            final WorkingPlaceholder wp = new WorkingPlaceholder();
            // we're going to hold up all incomming message to this mp
            // this blocks other threads from
            wp.mailbox.getAndSet(null);
            // dropping messages in the mailbox
            // try to get a lock
            final WorkingPlaceholder alreadyThere = working.putIfAbsent(key, wp);
            if (alreadyThere == null) {
                // we got it the lock
                final Object instance = instances.get(key);
                if (instance != null) {
                    final Semaphore taskSepaphore = taskLock;
                    // This task will release the wrapper's lock.
                    final Runnable task = new Runnable() {

                        @Override
                        public void run() {
                            final List<KeyedMessageWithType> response;
                            try {
                                if (isRunning.get())
                                    response = invokeOperation(instance, Operation.output, null);
                                else
                                    response = null;
                            } finally {
                                // releases this back to the world
                                working.remove(key);
                                // this signals that we're done.
                                synchronized (numExecutingOutputs) {
                                    numExecutingOutputs.decrementAndGet();
                                    numExecutingOutputs.notifyAll();
                                }
                                if (taskSepaphore != null)
                                    taskSepaphore.release();
                            }
                            if (response != null) {
                                try {
                                    dispatcher.dispatch(response);
                                } catch (final Exception de) {
                                    if (isRunning.get())
                                        LOGGER.warn("Failed on subsequent dispatch of " + response + ": " + de.getLocalizedMessage());
                                }
                            }
                        }
                    };
                    synchronized (numExecutingOutputs) {
                        numExecutingOutputs.incrementAndGet();
                    }
                    if (executorService != null) {
                        try {
                            taskSepaphore.acquire();
                            executorService.execute(task);
                        } catch (final RejectedExecutionException e) {
                            // we never got into the run so we need to release the lock
                            working.remove(key);
                            // this may happen because of a race condition between the
                            taskSepaphore.release();
                        } catch (final InterruptedException e) {
                            // this can happen while blocked in the semaphore.acquire.
                            // if we're no longer running we should just get out
                            // of here.
                            // 
                            // Not releasing the taskSepaphore assumes the acquire never executed.
                            // if (since) the acquire never executed we also need to release the
                            // wrapper lock or that Mp will never be usable again.
                            // we never got into the run so we need to release the lock
                            working.remove(key);
                        }
                    } else
                        task.run();
                    iter.remove();
                } else {
                    working.remove(key);
                    LOGGER.warn("There was an attempt to evict a non-existent Mp for key " + SafeString.objectDescription(key));
                }
            }
        // didn't get the lock
        }
    // loop over every mp
    }
    // now make sure all of the running tasks have completed
    synchronized (numExecutingOutputs) {
        while (numExecutingOutputs.get() > 0) {
            try {
                numExecutingOutputs.wait();
            } catch (final InterruptedException e) {
                // waiting for all of the threads to finish
                if (!isRunning.get())
                    break;
            // otherwise continue checking.
            }
        }
    }
// =======================================================
}
Also used : Semaphore(java.util.concurrent.Semaphore) LinkedList(java.util.LinkedList) ContainerException(net.dempsy.container.ContainerException) DempsyException(net.dempsy.DempsyException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) AtomicLong(java.util.concurrent.atomic.AtomicLong) Executor(java.util.concurrent.Executor) KeyedMessageWithType(net.dempsy.messages.KeyedMessageWithType)

Aggregations

KeyedMessageWithType (net.dempsy.messages.KeyedMessageWithType)26 Test (org.junit.Test)21 InstanceWrapper (net.dempsy.container.locking.LockingContainer.InstanceWrapper)7 NodeAddress (net.dempsy.transport.NodeAddress)5 DempsyException (net.dempsy.DempsyException)4 Container (net.dempsy.container.Container)4 RoutingStrategy (net.dempsy.router.RoutingStrategy)4 ContainerAddress (net.dempsy.router.RoutingStrategy.ContainerAddress)4 Assert.assertTrue (org.junit.Assert.assertTrue)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)3 Infrastructure (net.dempsy.Infrastructure)3 Manager (net.dempsy.Manager)3 ClusterInfoException (net.dempsy.cluster.ClusterInfoException)3 ClusterInfoSession (net.dempsy.cluster.ClusterInfoSession)3 ClusterId (net.dempsy.config.ClusterId)3 ContainerException (net.dempsy.container.ContainerException)3 KeyedMessage (net.dempsy.messages.KeyedMessage)3 RoutingStrategyManager (net.dempsy.router.RoutingStrategyManager)3