Extent notifier

The extent method in Extent<T> notifiers is called when the application calls ManagedObject.extent(...). The extent method is called on all nodes that are part of a distributed query on which Extent<T> notifiers are installed. If a notifier is not installed on a node participating in a distributed query, the query succeeds without calling a notifier on that node.

The extent method is executed synchronously before the application performs the first iteration on the returned extent Iterator. The extent notifier controls the objects that will be returned in the extent iterator by creating and deleting managed objects as required.

[Warning]

Extent queries against large data sets can cause significant resource consumption, both memory and CPU, as managed objects are created and updated. Care should be taken to not negatively impact application performance during extent queries.

When an Extent<T> notifier is installed it is also installed on all child types, unless there is already a notifier installed on the child types. When an extent iteration is performed on a type, the extent method is called on all children first, starting at the most distant child and traversing up the inheritance hierarchy. In the case where an Extent<T> notifier is only installed on a base type, the extent method will be called once for each child in the type hierarchy. The klass parameter to the extent method can be used to determine the specific type on which the extent method is currently being called.

The application requested LockMode is in the lockMode parameter. The notifier should attempt to honor the requested lockMode, but there is no enforcement.

Example 10.3. Extent notifier

//     $Revision: 1.1.2.3 $
package com.kabira.snippets.store;

import com.kabira.platform.LockMode;
import com.kabira.platform.ManagedObject;
import com.kabira.platform.Transaction;
import com.kabira.platform.annotation.Managed;
import com.kabira.store.Extent;

/**
 * Secondary store extent notifier
 * <p>
 * <h2> Target Nodes</h2>
 * <ul>
 * <li> <b>domainnode</b> = A
 * </ul>
 */
public class ExtentNotifier
{
    @Managed
    private static class Parent { };
    private static class Child extends Parent { };
    
    private static class Notifier extends Extent<Parent>
    {
        public Notifier()
        {
            super(Parent.class);
        }
        
        @Override
        public void extent(Class<? extends Parent> type, LockMode lockMode)
        {
            //
            //  Extent query on parent
            //
            if (type.equals(Parent.class) == true)
            {
                System.out.println("INFO: Extent called on parent");

                //
                //  Create some parent objects to return to application
                //
                new Parent();
                new Parent();
            }
            //
            //  Extent query on child
            //
            else
            {
                assert type.equals(Child.class) : type;
                
                System.out.println("INFO: Extent called on child");
                
                //
                //  Create some child objects to return to application
                //
                new Child();
                new Child();
            } 
        }
    }
	
    /**
     * Main entry point
     * @param args  Not used
     */
    public static void main(final String [ ] args)
    {
        //
        //  Install extent notifier for Parent type
        //
        new Transaction("Install")
        {
            @Override
            protected void run() throws Transaction.Rollback
            {
                new Notifier();
            }
        }.execute();
        
        new Transaction("Extent Query")
        {
            @Override
            protected void run() throws Transaction.Rollback
            {
                //
                //  Perform extent query on child
                //
                for (Child c : ManagedObject.extent(Child.class))
                {
                    System.out.println("INFO:\t" + c);
                }
                
                //
                //  Perform extent query on parent
                //
                for (Parent p : ManagedObject.extent(Parent.class))
                {
                    System.out.println("INFO:\t" + p);
                }        
            }
        }.execute();
    }
}


When the Example 10.3, “Extent notifier” is run it outputs these messages (annotation added):

#
# Extent query performed on Child
#
INFO: Extent called on child
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@865069a6
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@25d51d22

#
# Extent query performed on Parent.  extent method called
# twice - once for Child and once for Parent 
#
INFO: Extent called on child
INFO: Extent called on parent
INFO:    com.kabira.snippets.store.ExtentNotifier$Parent@4c936ce7
INFO:    com.kabira.snippets.store.ExtentNotifier$Parent@ec182063
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@1ae3c08c
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@ba687408
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@865069a6
INFO:    com.kabira.snippets.store.ExtentNotifier$Child@25d51d22