use of net.dempsy.container.ContainerException 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 keyedMessage, final Operation op, final boolean youOwnMessage) throws IllegalArgumentException, ContainerException {
if (keyedMessage == null)
// No. We didn't process the null message
return;
if (keyedMessage.message == null)
throw new IllegalArgumentException("the container for " + clusterId + " attempted to dispatch a null message.");
final boolean callDisposition = !(youOwnMessage || op == Operation.output);
final Object actualMessage = callDisposition ? disposition.replicate(keyedMessage.message) : keyedMessage.message;
final Object messageKey = keyedMessage.key;
if (messageKey == null) {
if (callDisposition)
disposition.dispose(actualMessage);
throw new ContainerException("Message " + objectDescription(actualMessage) + " contains no key.");
}
if (!inbound.doesMessageKeyBelongToNode(messageKey)) {
if (callDisposition)
disposition.dispose(actualMessage);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Message with key " + SafeString.objectDescription(messageKey) + " sent to wrong container. ");
if (op != Operation.output)
statCollector.messageFailed(1);
return;
}
boolean evictedAndBlocking;
try {
numBeingWorked.incrementAndGet();
do {
evictedAndBlocking = false;
final InstanceWrapper wrapper = getInstanceForKey(messageKey, actualMessage);
// wrapper will be null if the activate returns 'false'
if (wrapper != null) {
final Object instance = wrapper.getExclusive();
if (instance != null) {
// null indicates we didn't get the lock
try (QuietCloseable qc = () -> wrapper.releaseLock()) {
if (wrapper.isEvicted()) {
// if we're not blocking then we need to just return a failure. Otherwise we want to try
// again because eventually the current Mp will be passivated and removed from the container
// and a subsequent call to getInstanceForDispatch will create a new one.
Thread.yield();
// we're going to try again.
evictedAndBlocking = true;
} else {
invokeOperationAndHandleDispose(wrapper.getInstance(), op, new KeyedMessage(messageKey, actualMessage));
}
}
} 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(actualMessage);
if (callDisposition)
disposition.dispose(actualMessage);
}
} 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));
if (callDisposition)
disposition.dispose(actualMessage);
// leave the do/while loop
break;
}
} while (evictedAndBlocking);
} finally {
numBeingWorked.decrementAndGet();
}
}
use of net.dempsy.container.ContainerException in project Dempsy by Dempsy.
the class LockingContainer method getInstanceForKey.
/**
* This is required to return non null or throw a ContainerException
*/
InstanceWrapper getInstanceForKey(final Object key, final Object message) throws ContainerException {
// common case has "no" contention
InstanceWrapper wrapper = instances.get(key);
if (wrapper != null)
return wrapper;
// otherwise we will be working to get one.
final Boolean tmplock = Boolean.TRUE;
Boolean lock = keysBeingWorked.putIfAbsent(key, tmplock);
if (lock == null)
lock = tmplock;
// otherwise we'll do an atomic check-and-update
synchronized (lock) {
// double checked lock?????
wrapper = instances.get(key);
if (wrapper != null)
return wrapper;
Object instance = null;
try {
instance = prototype.newInstance();
} catch (final DempsyException e) {
if (e.userCaused()) {
LOGGER.warn("The message processor prototype " + SafeString.valueOf(prototype) + " threw an exception when trying to create a new message processor for they key " + SafeString.objectDescription(key), e.userCause);
statCollector.messageFailed(1);
instance = null;
} else
throw new ContainerException("the container for " + clusterId + " failed to create a new instance of " + SafeString.valueOf(prototype) + " for the key " + SafeString.objectDescription(key) + " because the clone method threw an exception.", e);
} catch (final RuntimeException e) {
throw new ContainerException("the container for " + clusterId + " failed to create a new instance of " + SafeString.valueOf(prototype) + " for the key " + SafeString.objectDescription(key) + " because the clone invocation resulted in an unknown exception.", e);
}
// activate
boolean activateSuccessful = false;
try {
if (instance != null) {
if (LOGGER.isTraceEnabled())
LOGGER.trace("the container for " + clusterId + " is activating instance " + String.valueOf(instance) + " via " + SafeString.valueOf(prototype) + " for " + SafeString.valueOf(key));
prototype.activate(instance, key, message);
activateSuccessful = true;
}
} catch (final DempsyException e) {
if (e.userCaused()) {
LOGGER.warn("The message processor " + SafeString.objectDescription(instance) + " activate call threw an exception.", e.userCause);
statCollector.messageFailed(1);
} else
throw new ContainerException("the container for " + clusterId + " failed to invoke the activate method of " + SafeString.valueOf(prototype) + ". Is the active method accessible - the class is public and the method is public?", e);
} catch (final RuntimeException e) {
throw new ContainerException("the container for " + clusterId + " failed to invoke the activate method of " + SafeString.valueOf(prototype) + " because of an unknown exception.", e);
}
if (activateSuccessful) {
// we only want to create a wrapper and place the instance into the container
// if the instance activated correctly. If we got here then the above try block
// must have been successful.
// null check above.
wrapper = new InstanceWrapper(instance);
// once it goes into the map, we can remove it from the 'being worked' set
instances.put(key, wrapper);
// remove it from the keysBeingWorked since any subsequent call will get
keysBeingWorked.remove(key);
// the newly added one.
statCollector.messageProcessorCreated(key);
}
return wrapper;
}
}
use of net.dempsy.container.ContainerException in project Dempsy by Dempsy.
the class NonLockingAltContainer method getInstanceForKey.
/**
* This is required to return non null or throw a ContainerException
*/
protected InstanceWrapper getInstanceForKey(final Object key, final Object actualMessage) throws ContainerException {
// common case has "no" contention
InstanceWrapper wrapper = instances.get(key);
if (wrapper != null)
return wrapper;
// otherwise we will be working to get one.
final Boolean tmplock = Boolean.TRUE;
Boolean lock = keysBeingWorked.putIfAbsent(key, tmplock);
if (lock == null)
lock = tmplock;
// otherwise we'll do an atomic check-and-update
synchronized (lock) {
// double checked lock?????
wrapper = instances.get(key);
if (wrapper != null)
return wrapper;
Object instance = null;
try {
instance = prototype.newInstance();
} catch (final DempsyException e) {
if (e.userCaused()) {
LOGGER.warn("The message processor prototype " + SafeString.valueOf(prototype) + " threw an exception when trying to create a new message processor for they key " + SafeString.objectDescription(key), e.userCause);
statCollector.messageFailed(1);
instance = null;
} else
throw new ContainerException("the container for " + clusterId + " failed to create a new instance of " + SafeString.valueOf(prototype) + " for the key " + SafeString.objectDescription(key) + " because the clone method threw an exception.", e);
} catch (final RuntimeException e) {
throw new ContainerException("the container for " + clusterId + " failed to create a new instance of " + SafeString.valueOf(prototype) + " for the key " + SafeString.objectDescription(key) + " because the clone invocation resulted in an unknown exception.", e);
}
if (instance == null)
throw new ContainerException("the container for " + clusterId + " failed to create a new instance of " + SafeString.valueOf(prototype) + " for the key " + SafeString.objectDescription(key) + ". The value returned from the clone call appears to be null.");
// activate
boolean activateSuccessful = false;
try {
if (instance != null) {
if (LOGGER.isTraceEnabled())
LOGGER.trace("the container for " + clusterId + " is activating instance " + String.valueOf(instance) + " via " + SafeString.valueOf(prototype) + " for " + SafeString.valueOf(key));
prototype.activate(instance, key, actualMessage);
activateSuccessful = true;
}
} catch (final DempsyException e) {
if (e.userCaused()) {
LOGGER.warn("The message processor " + SafeString.objectDescription(instance) + " activate call threw an exception.", e.userCause);
statCollector.messageFailed(1);
instance = null;
} else
throw new ContainerException("the container for " + clusterId + " failed to invoke the activate method of " + SafeString.valueOf(prototype) + ". Is the active method accessible - the class is public and the method is public?", e);
} catch (final RuntimeException e) {
throw new ContainerException("the container for " + clusterId + " failed to invoke the activate method of " + SafeString.valueOf(prototype) + " because of an unknown exception.", e);
}
if (activateSuccessful) {
// we only want to create a wrapper and place the instance into the container
// if the instance activated correctly. If we got here then the above try block
// must have been successful.
// null check above.
wrapper = new InstanceWrapper(instance);
// once it goes into the map, we can remove it from the 'being
instances.putIfAbsent(key, wrapper);
// worked' set
// remove it from the keysBeingWorked since any subsequent call will get
keysBeingWorked.remove(key);
// the newly added one.
statCollector.messageProcessorCreated(key);
}
return wrapper;
}
}
use of net.dempsy.container.ContainerException 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();
}
}
use of net.dempsy.container.ContainerException in project Dempsy by Dempsy.
the class NonLockingAltContainer 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 (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.");
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;
}
numBeingWorked.incrementAndGet();
boolean instanceDone = false;
while (!instanceDone) {
instanceDone = true;
final InstanceWrapper wrapper = getInstanceForKey(message.key);
// wrapper will be null if the activate returns 'false'
if (wrapper != null) {
final MutRef<WorkingQueueHolder> mref = new MutRef<>();
boolean messageDone = false;
while (!messageDone) {
messageDone = true;
final WorkingQueueHolder mailbox = setIfAbsent(wrapper.mailbox, () -> mref.set(new WorkingQueueHolder(false)));
// if mailbox is null then I got it.
if (mailbox == null) {
// can't be null if I got the mailbox
final WorkingQueueHolder box = mref.ref;
// spin until I get the queue
final LinkedList<KeyedMessage> q = getQueue(box);
KeyedMessage toProcess = pushPop(q, message);
// put the queue back
box.queue.lazySet(q);
while (toProcess != null) {
invokeOperation(wrapper.instance, Operation.handle, toProcess);
numBeingWorked.getAndDecrement();
// get the next message
final LinkedList<KeyedMessage> queue = getQueue(box);
if (queue.size() == 0)
// we need to leave the queue out
break;
toProcess = queue.removeFirst();
box.queue.lazySet(queue);
}
// release the mailbox
wrapper.mailbox.set(null);
} else {
// we didn't get exclusive access so let's see if we can add the message to the mailbox
// make one try at putting the message in the mailbox.
final LinkedList<KeyedMessage> q = mailbox.queue.getAndSet(null);
if (q != null) {
// I got it!
q.add(message);
mailbox.queue.lazySet(q);
} else {
// see if we're evicted.
if (wrapper.evicted) {
instanceDone = false;
// start back at getting the instance.
break;
}
// start over from the top.
messageDone = false;
}
}
}
} 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;
}
}
}
Aggregations