public class ClientAsynchronousIterator<E> extends Object implements IAsynchronousIterator<E>, Serializable
RemoteAsynchronousIterator so that it looks like an
IAsynchronousIterator again.
This implementation uses the caller's ExecutorService to run a task
that migrates data from the remote IAsynchronousIterator into a local
BlockingBuffer. The client implementation uses purely local
operations to test the contents of the local BlockingBuffer. This
means that operations like hasNext(long, TimeUnit) may be used with
short timeouts without possibility of blocking IO.
Note: This class is NOT thread-safe. There should be only a single process draining the iterator.
Note: In order to conserve resources, the caller is advised to use
start(ExecutorService) before making any other requests. This will
allow the caller to specify an ExecutorService that will be tasked
with buffering elements from the RemoteAsynchronousIterator. When
start(ExecutorService) is not invoked explicitly, a new
Thread will be allocated. Typically, an ExecutorService can
be much more efficient than creating a new Thread.
| Modifier and Type | Field and Description |
|---|---|
protected static boolean |
DEBUG |
protected static boolean |
INFO |
protected static org.apache.log4j.Logger |
log |
protected static long |
timeout
Timeout for the
ReaderTask when it invokes
RemoteAsynchronousIterator.hasNext(long, TimeUnit). |
protected static boolean |
trace
Enables low-level trace of the
ReaderTask. |
protected static TimeUnit |
unit
The units for
timeout. |
| Constructor and Description |
|---|
ClientAsynchronousIterator(RemoteAsynchronousIterator<E> remoteIterator,
int capacity) |
| Modifier and Type | Method and Description |
|---|---|
void |
close()
Notes that the iterator is closed and hence may no longer be read.
|
boolean |
hasNext() |
boolean |
hasNext(long timeout,
TimeUnit unit)
Return
true iff there is at least one element that can be
visited. |
boolean |
isExhausted()
Return
true iff this iterator will not visit any more
elements (non-blocking). |
E |
next() |
E |
next(long timeout,
TimeUnit unit)
Waits up to the timeout to return the next element.
|
void |
remove()
Operation is not supported.
|
protected void |
start()
Start the
ReaderTask iff it is not already running. |
void |
start(ExecutorService executorService)
Start the
ReaderTask that will populate the local buffer with
elements from the remote iterator. |
protected static final transient org.apache.log4j.Logger log
protected static final transient boolean INFO
protected static final transient boolean DEBUG
protected static final transient long timeout
ReaderTask when it invokes
RemoteAsynchronousIterator.hasNext(long, TimeUnit).
Note: A timeout is used instead of
RemoteAsynchronousIterator.hasNext() in order to avoid blocking
during an RMI call on a remote thread.
protected static final transient boolean trace
ReaderTask.public ClientAsynchronousIterator(RemoteAsynchronousIterator<E> remoteIterator, int capacity)
remoteIterator - A proxy for the remote iterator from which the elements are
being read.capacity - The capacity of the internal IBlockingBuffer.public void start(ExecutorService executorService)
ReaderTask that will populate the local buffer with
elements from the remote iterator.
When start(ExecutorService) is not invoked explicitly, a new
Thread will be allocated and the ReaderTask will be run
on that Thread. Typically, an ExecutorService can be
much more efficient than creating a new Thread. Therefore the
caller is encourged to break encapsulation and specify the
ExecutorService on which the ReaderTask will run
directly.
IllegalStateException - if the ReaderTask is already running.protected final void start()
ReaderTask iff it is not already running.public void close()
IAsynchronousIteratorIBlockingBuffer from
filling up and deadlocking. For this reason, IAsynchronousIterator.close() has
consequences NOT entailed by ICloseableIterator.
Note: Depending on the semantics of the producer, it MAY choose to treat
an interrupt() as normal (but eager) termination. For example, rule
execution treats an interrupt() as normal (but eager) termination with
the consequence that queries may be safely interrupted once some limit
has been satisfied. However, the preferred way to treat LIMIT is using
IRule with an IQueryOptions that specifies a LIMIT.
close in interface IAsynchronousIterator<E>close in interface ICloseableclose in interface ICloseableIterator<E>public boolean hasNext(long timeout,
TimeUnit unit)
throws InterruptedException
IAsynchronousIteratortrue iff there is at least one element that can be
visited. If the buffer is empty then this will block until: (a) an
element appears in the buffer; (b) the buffer is
BlockingBuffer.close()ed; or (c) the timeout expires.
Note that a false return DOES NOT signify that the iterator
is exhausted. However, if you specify an infinite timeout using
Long.MAX_VALUE TimeUnit.SECONDS then you MAY safely
interpret a false return as an indication that the iterator
is exhausted.
hasNext in interface IAsynchronousIterator<E>timeout - The length of time that the method may block awaiting an
element to appear.unit - The units in which the timeout is expressed.true iff there is an element available.InterruptedException - if the current thread is interrupted while waiting another
element.public boolean isExhausted()
IAsynchronousIteratortrue iff this iterator will not visit any more
elements (non-blocking).isExhausted in interface IAsynchronousIterator<E>true iff the iterator is known to be exhausted
without blocking. A false return does NOT imply
that the iterator will visit more elements, only that it MIGHT
visit more elements.public E next(long timeout, TimeUnit unit) throws InterruptedException
IAsynchronousIteratornext in interface IAsynchronousIterator<E>timeout - The timeout (overrides the chunkTimeout specified to
the BlockingBuffer ctor).unit - The unit in which the timeout is expressed.null iff the timeout was exceeded
before IAsynchronousIterator.hasNext(long, TimeUnit) returned
true.
In order to have a definitive indication that the iterator is
exhausted you need to invoke Iterator.hasNext() without a timeout
(blocking) or IAsynchronousIterator.isExhausted() (non-blocking).
InterruptedException - if the current thread is interrupted while waiting for
another element.public void remove()
remove in interface Iterator<E>UnsupportedOperationException - always.Copyright © 2006–2019 SYSTAP, LLC DBA Blazegraph. All rights reserved.