drill-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Chris Westin (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DRILL-2502) Improve code safety by providing a generic event delivery mechanism that supports queueing
Date Thu, 19 Mar 2015 21:07:38 GMT

    [ https://issues.apache.org/jira/browse/DRILL-2502?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14370111#comment-14370111

Chris Westin commented on DRILL-2502:

Something like this:

public abstract class EventProcessor<T> {
	private final LinkedList<T> queuedEvents = new LinkedList<>();
	private volatile boolean isProcessing = false;

	public EventProcessor() {

	public void sendEvent(final T newEvent) {
		synchronized(queuedEvents) {
			if (isProcessing) {
			} else {
				isProcessing = true;

		T event = newEvent;
		while(true) {
			try {
			} catch(Exception e) {
				// TODO
			} catch(AssertionError ae) {
				// TODO

			synchronized(queuedEvents) {
				if (queuedEvents.isEmpty()) {
					isProcessing = false;

			event = queuedEvents.removeFirst();

	protected abstract void processEvent(T event);

> Improve code safety by providing a generic event delivery mechanism that supports queueing
> ------------------------------------------------------------------------------------------
>                 Key: DRILL-2502
>                 URL: https://issues.apache.org/jira/browse/DRILL-2502
>             Project: Apache Drill
>          Issue Type: Bug
>          Components: Execution - Flow
>            Reporter: Chris Westin
>            Assignee: Chris Westin
> While working on DRILL-2245, I ran into problems because Foreman.moveToState() can be
called recursively. Being synchronized doesn't prevent the same thread from calling back into
this. When this happens, state transitions are either dropped or broken depending on when
this happens. This event really needs to be handled atomically, but when queryContext.cancelExecutingFragments()
is called, the completion of the cancellations results in QueryManager.fragmentDone() being
called, and it indiscriminately sends the COMPLETED state, even though we may be in the middle
of handling a move to FAILED or CANCELLATION_REQUESTED. Unless the target state is first recorded
before any possible recursive call happens, the recursive transition is recorded, and the
second transition doesn't result in any message being sent to the user -- the client hangs.
> It's difficult to reason about when its safe for this kind of recursive call to happen,
and even more difficult to avoid inadvertently introducing these. Problems happen when the
delivery of an event to a listener causes cascaded events that eventually deliver to the same
> In order to avoid this, we should create (and use) a generic class that can receive such
events. If nothing is happening when one is received, it is processed immediately, in line.
If an event is received when we're in the middle of processing another event, the newly received
one is queued. When the current event processing is completed, we then go through any queued
events, and process them one by one. We continue in this way until there are no more events
left, then return. This mechanism would improve code safety by preventing the delivery of
events while in the middle of processing other events by the same handler.

This message was sent by Atlassian JIRA

View raw message