001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.spi;
018
019import java.util.Collection;
020import java.util.concurrent.CountDownLatch;
021
022import org.apache.camel.Exchange;
023import org.apache.camel.StaticService;
024
025/**
026 * A manager to handle async routing engine, when {@link Exchange}s are being handed over from one thread to another, while
027 * the callee thread is blocked waiting for the other threads to complete, before it can continue.
028 * <p/>
029 * This manager offers insight into the state, and allow to force stuck exchanges to be continued and for blocked threads
030 * to be unblocked, which may happen in case of severe malfunctions (such as the system runs out of memory, a 3rd party
031 * never responding, or a timeout not triggering, etc).
032 */
033public interface AsyncProcessorAwaitManager extends StaticService {
034
035    /**
036     * Utilization statistics of the this manager.
037     */
038    interface Statistics {
039
040        /**
041         * Total number of threads that has been blocked
042         */
043        long getThreadsBlocked();
044
045        /**
046         * Total number of threads that has been forced interrupted
047         */
048        long getThreadsInterrupted();
049
050        /**
051         * The total duration time in millis.
052         */
053        long getTotalDuration();
054
055        /**
056         * The lowest duration time in millis.
057         */
058        long getMinDuration();
059
060        /**
061         * The highest duration time in millis.
062         */
063        long getMaxDuration();
064
065        /**
066         * The average duration time in millis.
067         */
068        long getMeanDuration();
069
070        /**
071         * Reset the counters
072         */
073        void reset();
074
075        /**
076         * Whether statistics is enabled.
077         */
078        boolean isStatisticsEnabled();
079
080        /**
081         * Sets whether statistics is enabled.
082         *
083         * @param statisticsEnabled <tt>true</tt> to enable
084         */
085        void setStatisticsEnabled(boolean statisticsEnabled);
086    }
087
088    /**
089     * Information about the thread and exchange that are inflight.
090     */
091    interface AwaitThread {
092
093        /**
094         * The thread which is blocked waiting for other threads to signal the callback.
095         */
096        Thread getBlockedThread();
097
098        /**
099         * The exchange being processed by the other thread.
100         */
101        Exchange getExchange();
102
103        /**
104         * Time in millis the thread has been blocked waiting for the signal.
105         */
106        long getWaitDuration();
107
108        /**
109         * The id of the route where the exchange was processed when the thread was set to block.
110         * <p/>
111         * Is <tt>null</tt> if message history is disabled.
112         */
113        String getRouteId();
114
115        /**
116         * The id of the node from the route where the exchange was processed when the thread was set to block.
117         * <p/>
118         * Is <tt>null</tt> if message history is disabled.
119         */
120        String getNodeId();
121
122    }
123
124    /**
125     * Registers the exchange to await for the callback to be triggered by another thread which has taken over processing
126     * this exchange. The current thread will await until that callback happens in the future (blocking until this happens).
127     *
128     * @param exchange   the exchange
129     * @param latch      the latch used to wait for other thread to signal when its done
130     */
131    void await(Exchange exchange, CountDownLatch latch);
132
133    /**
134     * Triggered when the other thread is done processing the exchange, to signal to the waiting thread is done, and can take
135     * over control to further process the exchange.
136     *
137     * @param exchange   the exchange
138     * @param latch      the latch used to wait for other thread to signal when its done
139     */
140    void countDown(Exchange exchange, CountDownLatch latch);
141
142    /**
143     * Number of threads that are blocked waiting for other threads to trigger the callback when they are done processing
144     * the exchange.
145     */
146    int size();
147
148    /**
149     * A <i>read-only</i> browser of the {@link AwaitThread}s that are currently inflight.
150     */
151    Collection<AwaitThread> browse();
152
153    /**
154     * To interrupt an exchange which may seem as stuck, to force the exchange to continue,
155     * allowing any blocking thread to be released.
156     * <p/>
157     * <b>Important:</b> Use this with caution as the other thread is still assumed to be process the exchange. Though
158     * if it appears as the exchange is <i>stuck</i>, then this method can remedy this, by forcing the latch to count-down
159     * so the blocked thread can continue. An exception is set on the exchange which allows Camel's error handler to deal
160     * with this malfunctioned exchange.
161     *
162     * @param exchangeId    the exchange id to interrupt.
163     */
164    void interrupt(String exchangeId);
165
166    /**
167     * To interrupt an exchange which may seem as stuck, to force the exchange to continue,
168     * allowing any blocking thread to be released.
169     * <p/>
170     * <b>Important:</b> Use this with caution as the other thread is still assumed to be process the exchange. Though
171     * if it appears as the exchange is <i>stuck</i>, then this method can remedy this, by forcing the latch to count-down
172     * so the blocked thread can continue. An exception is set on the exchange which allows Camel's error handler to deal
173     * with this malfunctioned exchange.
174     *
175     * @param exchange    the exchange to interrupt.
176     */
177    void interrupt(Exchange exchange);
178
179    /**
180     * Whether to interrupt any blocking threads during stopping.
181     * <p/>
182     * This is enabled by default which allows Camel to release any blocked thread during shutting down Camel itself.
183     */
184    boolean isInterruptThreadsWhileStopping();
185
186    /**
187     * Sets whether to interrupt any blocking threads during stopping.
188     * <p/>
189     * This is enabled by default which allows Camel to release any blocked thread during shutting down Camel itself.
190     */
191    void setInterruptThreadsWhileStopping(boolean interruptThreadsWhileStopping);
192
193    /**
194     * Gets the utilization statistics of this manager
195     *
196     * @return the utilization statistics
197     */
198    Statistics getStatistics();
199
200}