JavaSpaces Iterator

  Search Here
Searching XAP 6.0 Documentation

                                               

There are two main ways to use the GSIterator:

MatchSet Iterator - GSIterator

The GSIterator is based on the net.jini.space.MatchSet interface and provides the ability to exhaustively read through all of the Entries from a JavaSpaces service that match one or more templates.

There are scenarios where the conventional read operation that returns a single entry object does not fit and there is a need to return a collection of entries from the space. Generally, an iterator should be used because returning all the Entries in one result sent back to the call would consume too many resources in the client or introduce too much latency before the first Entry could be processed. The iterator constructs a match set (a collection of Entry instances) that incrementally returns the necessary Entries. The GSIterator constructs a proxy object that can be used to access a match set created by a space. The match set will initially contain some population of Entries specified by the operation that created it. These Entries can be retrieved by calling the next method. A successful call to next will remove the returned Entry from the match set. Match sets can end up in one of two terminal states: exhausted or invalidated.

A match set becomes exhausted or invalidated specified by the operation that created it under the following conditions:

  • An exhausted match set is empty and will have no more entries added. Calling next on an exhausted match set must always return null.
  • Calling next on an invalidated match set may return a non-null value, or it may return a NoSuchObjectException to indicate that the match set has been invalidated. Once next throws a NoSuchObjectException, all future next calls on that instance will throw NoSuchObjectException.
  • Calling next on an invalidated match set does not return null.
  • Entries are not added to an invalidated match set.

Between the time a match set is created and the time it reaches a terminal state, entries may be added by the space. However, an Entry that is removed by a next call must not be added back to a match set (though if there is a distinct but equivalent Entry in the space it may be added). The space may also remove Entries independent of next calls. The conditions under which Entries will be removed independent of next calls or added after the initial creation of the match set are specified by the operation that created the match set.

An active lease on a match set serves as a hint to the space that the client is still interested in the match set, and as a hint to the client that the match set is still functioning, i.e., if a match set is leased and the lease is active, GSIterator will maintain the match set and will not invalidate it.

If the iterator lease expires or is canceled, GSIterator will invalidate the match set. Clients should not assume that the resources associated with a leased match set will be freed automatically if the match set reaches the exhausted state, but should explicitly cancel the lease.

The GSIterator defines the matched set using the following parameters:

  • Collection of Entry templates.
  • Including or excluding existing matched Entries in the space.
  • Limit.
  • Lease, Renew Lease, Cancel Lease.
  • Next (returns Entry).
  • Blocking Next (next with timeout).
Using GSIterator with SQLQuery
When using the GSIterator with SQLQuery, only simple SQL queries (that can be translated to one regular template) are supported:
(field1 < value1) AND (field2 > value2) AND (field3 == values3)...

The following operators are not supported when using simple queries:

  • LIKE
  • OR
  • GROUP BY
  • ORDER BY

API - Constructor Summary

GSIterator(com.j_spaces.core.IJSpace space, java.util.Collection collectionTemplates)
GSIterator with default Iterator Buffer size (100 entries), without History property,
and Lease.FOREVER as the iterator lease.
GSIterator(com.j_spaces.core.IJSpace space, java.util.Collection collectionTemplates,
int bufferSize, boolean withHistory, long lease)
GSIterator Constructor
Return Value Method
void cancel()
Used by the lease holder to indicate that it is no longer interested in the iterator.
long getExpiration()
Returns the absolute time that the lease will expire, represented as milliseconds from the beginning of the epoch, relative to the local clock.
boolean hasNext()
Returns true if the iterator has more elements.
net.jini.core.entry.Entry next()
Returns the next matching-template Entry in the iterator.
net.jini.core.entry.Entry next(long timeout)
Blocking next with timeout – returns the next matching-template Entry in the iterator, under the timeout limitation.
void notify(net.jini.core.event.RemoteEvent event)
For internal use.
void renew(long duration)
Used to renew a lease for an additional period of time, specified in milliseconds.
net.jini.core.entry.Entry snapshot()
Returns a snapshot of the Entry returned by the last next call, as defined in section JS.2.6 of the JavaSpaces specification.

Initialization

When a GSIterator is created, a match set is formulated. The match set initially contains all of the Entries in the space that match one or more of the collection templates and are not locked by conflicting transactions (unless withHistory was set to false, i.e., no initial contents). Each element of the matched set will be returned at most once.

hasNext(), next() and next(timeout)

Calling hasNext() returns true if next returns a non-null element rather than throwing an exception. Calling next removes one element from the matched set and returns it to the caller. Calling next(timeout) blocks next. The iteration is said to be complete if the match set becomes empty or next calls limit (buffer size) has removed Entries from the match set. A next call returns null only if the iteration is complete.

take() and Entry Lease Expiration

An Entry may be, but is not required to be, removed from the match set without being returned by a next call if it is removed from the space or is locked by a conflicting transaction. GSIterator does not remove the Entry after it has been buffered.

Notifications

GSIterator uses the NotifyDelegator to register each of the templates in the templates collection. If a matching Entry was written to the space after the match set was created, the Entry will be added to the match set. An Entry that was locked under a conflicting transaction before or after the match set was created and the lock was released before the iteration was complete will also be added to the match set.

A matching that arrived from a notification event will interrupt any blocking next(timeout) operation. If a take operation was called or an Entry lease timeout, the Entry will be removed from the next iteration matched set.

Iterator Lease

In most cases, the iterator will be leased and the lease proxy object can be obtained by calling the getLease() method. Cancelling or letting the lease expire will destroy the iterator; thus no notifications from here on will be accounted for, and all subsequent calls to hasNext() will return false. If there is a lease associated with the iterator, clients should not assume that completing the iteration will destroy it and should instead call cancel or let the lease expire when the end of the iteration is reached. A lease renewal(timeout) is used to renew a lease for an additional period of time. This duration is not added to the original lease, but is used to determine a new expiration time for the existing lease. If a lease has expired or has been canceled, a renewal is not allowed.

Transactions

Iterating through the matched set does not lock the Entry. Entries that are under transaction and match the specified template will not be included as part of the matched set.

snapshot

The snapshot method returns a snapshot of the Entry returned by the last next call (see section JS.2.6 of the JavaSpaces specification). If the last next call returned null or failed with an exception or error, the snapshot will throw an IllegalStateException. It is important to note that the GSIterator.snapshot(), unlike the JavaSpace.snapshot(), does not throw a RemoteException.

The GSIterator uses the following NotifyModifiers:
  • NotifyModifiers.NOTIFY_WRITE – updates the Iterator with a new Entry.
  • NotifyModifiers.NOTIFY_TAKE and NotifyModifiers.NOTIFY_LEASE_EXPIRATION – removes an Entry from the Iterator.
    Updates do affect the iterator.

Example

In GigaSpaces 6.0, and it is recommended to use the GSIterator as shown in the Enterprise Data Grid Tutorial B - Aggregate Queries section. The usage described in this section is still supported.

The following code example invokes two threads – a writer and a reader thread.

The writer thread writes Entries to the space. The reader thread uses an iterator that iterates through all the matching Entries that match the specified templates in the pre-defined collection. If no matches are found, the reader uses the next with blocking option that waits until either a new match is found or a timeout occurs. When a matched Entry is found, the iterator lease is renewed. When the next is timed out, the iterator is canceled.

package com.j_spaces.examples.iterator;
import java.util.ArrayList;
import java.util.Collection;
import net.jini.core.entry.Entry;
import net.jini.core.lease.Lease;
import com.j_spaces.core.IJSpace;
import com.j_spaces.core.client.FinderException;
import com.j_spaces.core.client.GSIterator;
import com.j_spaces.core.client.SpaceFinder;
public class Iterator
{
	public static class SpaceWriter implements Runnable
	{
		public final static int NUM_OF_MESSAGES = 5;
		public final static int WRITE_CYCLES = 3;
		public final static long SLEEP_TIME = 5000; //5 sec
		IJSpace space;

		public SpaceWriter(IJSpace space)
		{
			this.space = space;
		}


		/**
		 * Write entries to the space, one even one odd.
		 * Sleep after each cycle of N messages.
		 */
		public void run()
		{
			int id = 0;

			try
			{
				//break loop after 5 cycles
				for (int i=0; i < WRITE_CYCLES; i++)
				{
					System.out.println("[  Writer  ]tWriter Thread writing "
							+ NUM_OF_MESSAGES + " messages");

					for (int j=0; j < NUM_OF_MESSAGES; j++){
						id = i*NUM_OF_MESSAGES +j;
						if (id%2==0)
							space.write( new Even(id), null, Lease.FOREVER );
						else
							space.write( new Odd(id), null, Lease.FOREVER );
					}

					System.out.println("[  Writer  ]tWriter Thread sleeping for "
							+ SLEEP_TIME/1000 + " seconds");

					Thread.sleep(SLEEP_TIME);

				}

				System.out.println("[  Writer  ]tWriter Thread finished "
						+ WRITE_CYCLES + " write cycles of "
						+ NUM_OF_MESSAGES + " messages. "
						+ "n[  Writer  ]tDone.");
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}

		}



	}
	public static class SpaceIterator implements Runnable
	{
		public final static long BLOCK_TIME = 5000; // 5 sec
		public final static long LEASE_TIME = 10000;// 10 sec
		IJSpace space;
		GSIterator gsIterator;

		public SpaceIterator(IJSpace space)
		{
			this.space = space;

			/*
			 * build a collection of 2 templates:
			 * An odd numbered template and
			 * an even numbered template.
			 *
			 * You could also pass a collection with a null template.
			 */
			Collection col = new ArrayList();
			col.add(new Even());
			col.add(new Odd());

			try
			{
				/*
				 * create an iterator of the space with the
				 * specified collection.
				 *
				 * The buffer window is the limit of entries
				 * to store for each iteration.
				 *
				 * The with history flag indicates that this
				 * iterator will be pre-filled with matching entries;
				 * otherwise it will start iterating only on newly
				 * arriving entries at the space.
				 *
				 * The lease is the life time of this iterator
				 */
				System.out.println(
				"[ Iterator ]tCreating Iterator over space for Collection:");

				gsIterator = new GSIterator(space, // space ref.
						col, // templates collection
						10, // buffer "window" size
						true, // with history true
						LEASE_TIME);// lease  10 seconds
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}


		/**
		 * Iterate through all the entries matching the specified templates
		 * in the pre-defined collection.
		 *
		 * If no matches are found, try blocking the iterator until either
		 * a new match is found or a timeout occurs.
		 *  - When found, renew the iterator lease.
		 * - When timed out, cancel the iterator.
		 */
		public void run()
		{
			try
			{
				System.out.println("[ Iterator ]tIterator Thread reading messages");
				while (true)
				{
					//lets iterate until we don't have any more matches
					while (gsIterator.hasNext())
					{
						Entry entry = (Entry)gsIterator.next();
						printEntry(entry);
					}

					System.out.println("[ Iterator ]tNo more entries to iterate. Blocking next for "
							+ BLOCK_TIME/1000 + " seconds");

					//lets block the iterator until a new match is found
					Entry entry = (Entry)gsIterator.next(BLOCK_TIME);
					if (entry != null){
						System.out.println("[ Iterator ]tIterator un-blocked with a match");
						printEntry(entry);

					//lets renew the iterator and keep iterating.
						gsIterator.renew(LEASE_TIME);
					}
					else
					{
						System.out.println("[ Iterator ]tIterate un-blocked without a match");
						break;
					}

					/* NOTE
					 * An equivalent implementation is a blocking loop:
					 * --------------------------------------------------
					 * while (gsIterator.hasNext())
					 * {
					 * Entry entry = (Entry)gsIterator.next(BLOCK_TIME);
					 * printEntry(entry);
					 * }
					 */
				}

			   //An iteration was un-blocked without a match,
			  //lets cancel the iterator
				gsIterator.cancel();
				System.out.println("[ Iterator ]tIterator canceled.");
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}

		/**
		 * print the entry returned by the iteration
		 * @param entry An entry matching a template from the collection
		 */
		public void printEntry(Entry entry)
		{
			if (entry instanceof Even)
				System.out.println("[ Iterator ]tIterator Thread read: "
						+ entry + " - "+ ((Even)entry).tmplId);
			else
				System.out.println("[ Iterator ]tIterator Thread read: "
						+ entry + " - "+ ((Odd)entry).tmplId);
		}
	}
	public static void main(String[] args)
	{
		if ( args.length != 1 )
		{
			System.out.println("Usage: <URL>");
			System.out.println("jini://lookup host/container name/JavaSpaces");
			System.exit(1);
		}
		try
		{
			IJSpace space = (IJSpace)SpaceFinder.find( args[0] );
			if ( space == null )
			{
				System.out.println("t> Space not found: " + args[0]);
				System.exit(-1);
			}

			System.out.println("t> Space will now be set to run in FIFO mode.");
			space.setFifo(true);
			/**
			 * Lets create one iterator thread and one
			 * write thread.
			 *
			 * @see SpaceIterator#run()
			 * @see SpaceWriter#run()
			 */
			Thread[] threads = new Thread[2];
			threads[0] = new Thread(new Iterator.SpaceIterator(space));
			threads[Look And Feel - ServiceGrid] = new Thread(new Iterator.SpaceWriter(space));
			for (int i=0; i< threads.length; i++)
				threads[i].start();

			for (int i=0; i< threads.length; i++)
				threads[i].join();


			System.exit(0);
		}
		catch( FinderException ex )
		{
			ex.printStackTrace();
			System.out.println("t> Could not find space: " + args[0]);
			System.out.println("t> Please check that GigaSpaces Server is running.");
		}
		catch (Exception e){}
	}
}


IMPORTANT: This is an old version of GigaSpaces XAP. Click here for the latest version.
GigaSpaces 6.0 Documentation Contents (Current Page in Bold)

    Java

    C++

    .NET

    Middleware Capabilities

    Configuration and Management

Add GigaSpaces wiki search to your browser search engines!
(works on Firefox 2 and Internet Explorer 7)

Labels