directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: rev 20742 - in incubator/directory/rms/trunk: je/src/java/org/apache/rms/je je/src/java/org/apache/rms/je/profile spi/src/java/org/apache/rms/spi
Date Tue, 01 Jun 2004 18:58:38 GMT
Author: akarasulu
Date: Tue Jun  1 11:58:37 2004
New Revision: 20742

Added:
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeJoinIterator.java   (contents,
props changed)
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeSecondaryIterator.java  
(contents, props changed)
Modified:
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java
   incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
   incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitor.java
   incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitorAdapter.java
Log:
Commit changes ...

 o renamed old JeIterator to JeJoinIterator
 o factored out JeIterator interface from JeJoinIterator
 o created JeIterator impl JeSecondaryIterator for secondary cursors
 o made both JeIterator impls share the same monitor interface



Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java	(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeIterator.java	Tue Jun  1
11:58:37 2004
@@ -1,424 +1,57 @@
-/*
- *   Copyright 2004 The Apache Software Foundation
- *
- *   Licensed under the Apache License, Version 2.0 (the "License");
- *   you may not use this file except in compliance with the License.
- *   You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *   Unless required by applicable law or agreed to in writing, software
- *   distributed under the License is distributed on an "AS IS" BASIS,
- *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *   See the License for the specific language governing permission and
- *   limitations under the License.
- *
- */
-package org.apache.rms.je ;
-
-
-import java.util.Iterator ;
-import java.util.Observable ;
-import java.util.NoSuchElementException;
-
-import java.io.IOException ;
-
-import com.sleepycat.je.* ;
-import com.sleepycat.bind.EntryBinding ;
-
-
-/**
- * A JE iterator that tries to cleanup cursor resources when consumed or
- * failures result.
- *
- * Goals:
- * <ul>
- *   <li>Implement observable pattern to track open/closed cursors</li>
- *   <li>Keep it simple - other Iterators can wrap this one to customize</li>
- *   <li>Return raw pk or data or objects via optional binding</li>
- * </ul>
- * 
- * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
- * @version $Rev$
- */
-public class JeIterator extends Observable implements Iterator
-{
-    /** tracks if we have another item to return */
-    private boolean hasNext = true ;
-    /** the operation status of the last prefetch operation */
-    private OperationStatus status ;
-    /** the last prefetched item */
-    private Object prefetched ;
-    /** a monitor to track the events associated with this iterator */
-    private JeIteratorMonitor monitor ;
-    /** a failure if one has occurred */
-    private Throwable fault ;
-
-    /** the Join cursor that we wrap */
-    private final JoinCursor cursor ;
-    /** the database entry primary key populated */
-    private final DatabaseEntry pk ;
-    /** the database entry data populated */
-    private final DatabaseEntry data ;
-    /** the optional entry binding to use */
-    private final EntryBinding binding ;
-    /** the secondary cursors for the JoinCursor */
-    private final SecondaryCursor[] secCursors ;
-
-
-    /**
-     * Creates a JeIterator that iterates over primary key entries, values or
-     * bound object using an optional binding.
-     *
-     * @param cursor the underlying join cursor being wrapped
-     * @param secCursors due to a bug we need them to close em our selves
-     * @param binding optional binding to apply to pk or data before it is
-     * returned in the prefetch operation
-     * @param getBoth whether or not to fetch both the pk and the data - if
-     * true the data is fetched as well
-     */
-    public JeIterator( JoinCursor cursor, SecondaryCursor[] secCursors,
-                       EntryBinding binding, boolean getBoth )
-            throws DatabaseException, IOException
-    {
-        this.pk = new DatabaseEntry() ;
-        this.cursor = cursor ;
-        this.secCursors = secCursors ;
-        this.monitor = new JeIteratorMonitorAdapter() ;
-        this.binding = binding ;
-
-        if ( getBoth )
-        {
-            this.data = new DatabaseEntry() ;
-        }
-        else
-        {
-            this.data = null ;
-        }
-
-        try
-        {
-            prefetched = prefetch() ;
-        }
-        catch ( DatabaseException e )
-        {
-            close( e ) ;
-            monitor.prefetchFailure( this ) ;
-            throw e ;
-        }
-        catch ( IOException e )
-        {
-            close( e ) ;
-            monitor.prefetchFailure( this ) ;
-            throw e ;
-        }
-        catch ( Error e )
-        {
-            close( e ) ;
-            monitor.prefetchFailure( this ) ;
-            throw e ;
-        }
-    }
-
-
-    /**
-     * Remove is unsupported so calling this monitors the call, closes this
-     * iterator and throws an exception.
-     *
-     * @throws UnsupportedOperationException every time.
-     */
-    public final void remove()
-    {
-        UnsupportedOperationException fault ;
-
-        monitor.removeAttempted( this ) ;
-        fault = new UnsupportedOperationException() ;
-        close( fault ) ;
-
-        throw fault ;
-    }
-
-
-    /**
-     * Gets the boolean hasNext flag for this iterator.
-     *
-     * @return whether or not another data is available by calling next()
-     */
-    public final boolean hasNext()
-    {
-        return hasNext ;
-    }
-
-
-    /**
-     * Saves the last prefetched data which is returned but before returning
-     * it prefetches the next data.   Failures and succcesses are reported to
-     * the monitor.
-     *
-     * @return the next item in the iteration
-     */
-    public final Object next()
-    {
-        Object retval = prefetched ;
-
-        if ( ! hasNext )
-        {
-            throw new NoSuchElementException() ;
-        }
-
-        try
-        {
-            prefetched = prefetch() ;
-            monitor.prefetch( this, prefetched, retval ) ;
-        }
-        catch ( Exception e )
-        {
-            close( e ) ;
-            monitor.prefetchFailure( this, retval ) ;
-
-            if ( e instanceof RuntimeException )
-            {
-                throw ( RuntimeException ) e ;
-            }
-        }
-        catch ( Error e )
-        {
-            close( e ) ;
-            monitor.prefetchFailure( this, retval ) ;
-            throw e ;
-        }
-
-        return retval ;
-    }
-
-
-    /**
-     * Checks to see if this iterator was closed prematurely due to a failure
-     * or if it was closed by being consumed or by an intentional close call.
-     *
-     * @return true if this closed due to a failure, false otherwise
-     */
-    public final boolean hasFailed()
-    {
-        return fault != null ;
-    }
-
-
-    /**
-     * Gets the status of the last prefetch operation against a JE cursor.
-     *
-     * @return the status of the last prefetch operation
-     */
-    public final OperationStatus getStatus()
-    {
-        return status ;
-    }
-
-
-    /**
-     * Gets the failure that prematurely closed this cursor.
-     *
-     * @return the failure that prematurely closed this cursor, or null if
-     * no failures occured during cursor operation
-     */
-    public final Throwable getFault()
-    {
-        return fault ;
-    }
-
-
-    /**
-     * Gets the optional binding for this iterator.
-     *
-     * @return the optional binding for this iterator
-     */
-    public final EntryBinding getBinding()
-    {
-        return binding ;
-    }
-
-
-    /**
-     * Closes this iterator by setting hasNext flag perminantly to false and
-     * calling the cleanup method if the iterator was not closed before.
-     * Failure and success event notifications are sent via callback events
-     * to the monitor.  If any observers exist for this iterator they also are
-     * notified of the closing of this iterator.  hence
-     */
-    public final void close()
-    {
-        if ( ! hasNext )
-        {
-            return ;
-        }
-
-        hasNext = false ;
-        super.setChanged() ;
-
-        try
-        {
-            cleanup() ;
-        }
-        catch ( Exception e )
-        {
-            monitor.cleanupFailure( this, e ) ;
-            if ( e instanceof RuntimeException )
-            {
-                throw ( RuntimeException ) e ;
-            }
-        }
-        catch( Error e )
-        {
-            monitor.cleanupFailure( this, e ) ;
-            throw e ;
-        }
-
-        super.notifyObservers() ;
-        monitor.closed( this ) ;
-    }
-
-
-    /**
-     * Sets the monitor to be used by this iterator.
-     *
-     * @param monitor the monitor used for callback events
-     */
-    public final void setMonitor( JeIteratorMonitor monitor )
-    {
-        this.monitor = monitor ;
-    }
-
-
-    /**
-     * Gets whether or not this iterator fetches record data.
-     *
-     * @return whether or not this iterator fetches record data
-     */
-    public final boolean hasRecordData()
-    {
-        return data != null ;
-    }
-
-
-    // -----------------------------------------------------------------------
-    // Protected Methods
-    // -----------------------------------------------------------------------
-
-
-    /**
-     * Sets and returns the status for call chaining - closes this iterator if
-     * status is not equal to OperationStatus.SUCCESS.
-     *
-     * @param status the status to set
-     * @return the status argument for call chaining
-     */
-    private final OperationStatus setStatus( OperationStatus status )
-    {
-        this.status = status ;
-
-        if ( status != OperationStatus.SUCCESS )
-        {
-            close() ;
-        }
-
-        return this.status ;
-    }
-
-
-    /**
-     * Use this close method when failures cause this iterator to close
-     * prematurely, this sets the fault member of the class before a regular
-     * close call.
-     *
-     * @param fault a failure that caused this iterator to prematurely close
-     */
-    private final void close( Throwable fault )
-    {
-        this.fault = fault ;
-        close() ;
-    }
-
-
-    /**
-     * Concrete JeIterator's must allow for item prefetching.  This method is
-     * called usually once on initialization, and once every time next() is
-     * invoked.
-     *
-     * @return the a prefetched item from the iteration
-     * @throws DatabaseException if any failures accessing the database
-     * @throws DatabaseException if any failures occur while binding
-     */
-    private final Object prefetch() throws DatabaseException, IOException
-    {
-        if ( data != null )
-        {
-            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
-
-            if ( binding != null )
-            {
-                return binding.entryToObject( data ) ;
-            }
-
-            return data ;
-        }
-        else
-        {
-            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
-
-            if ( binding != null )
-            {
-                return binding.entryToObject( pk ) ;
-            }
-
-            return pk ;
-        }
-    }
-
-
-    /**
-     * Cleans up by closing the JoinCursor for this iterator which in turn
-     * should close all the SecondaryCursors used but this does not seem to
-     * work.  This should be overridden to close all the SecondaryCursors
-     * used to construct the JoinCursor.
-     *
-     * @throws DatabaseException on failures while closing the join cursor
-     */
-    private final void cleanup() throws DatabaseException
-    {
-        DatabaseException e = null ;
-
-        for( int ii = 0 ; ii < secCursors.length; ii++ )
-        {
-            try
-            {
-                if ( secCursors[ii] != null )
-                {
-                    secCursors[ii].close() ;
-                }
-            }
-            catch ( DatabaseException thrown )
-            {
-                e = thrown ;
-            }
-        }
-
-        if ( cursor != null )
-        {
-            cursor.close() ;
-
-            if ( e != null )
-            {
-                throw e ;
-            }
-        }
-    }
-
-
-    /**
-     * Finalizes this JeIterator by closing it.
-     */
-    public void finalize()
-    {
-        close() ;
-    }
-}
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je;
+
+
+import java.util.Iterator;
+
+import com.sleepycat.je.OperationStatus;
+import com.sleepycat.bind.EntryBinding;
+
+
+/**
+ * Document this class.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory
+ *         Project</a>
+ * @version $Rev$
+ */
+public interface JeIterator extends Iterator
+{
+    boolean hasFailed();
+
+
+    OperationStatus getStatus();
+
+
+    Throwable getFault();
+
+
+    EntryBinding getBinding();
+
+
+    void close();
+
+
+    void setMonitor( JeIteratorMonitor monitor );
+
+
+    boolean hasRecordData();
+
+
+    void finalize();
+}

Added: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeJoinIterator.java
==============================================================================
--- (empty file)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeJoinIterator.java	Tue Jun
 1 11:58:37 2004
@@ -0,0 +1,455 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permission and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je ;
+
+
+import java.util.Observable ;
+import java.util.NoSuchElementException ;
+
+import java.io.IOException ;
+
+import com.sleepycat.je.* ;
+import com.sleepycat.bind.EntryBinding ;
+
+
+/**
+ * A JE iterator over a join cursor based on several secondary cursors that
+ * tries to cleanup cursor resources when consumed or failures result.
+ *
+ * Goals:
+ * <ul>
+ *   <li>Implement observable pattern to track open/closed cursors</li>
+ *   <li>Keep it simple - other Iterators can wrap this one to customize</li>
+ *   <li>Return raw pk or data or objects via optional binding</li>
+ * </ul>
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory
+ * Project</a>
+ * @version $Rev$
+ */
+public class JeJoinIterator extends Observable
+        implements JeIterator
+{
+    /** tracks if we have another item to return */
+    private boolean hasNext = true ;
+    /** the operation status of the last prefetch operation */
+    private OperationStatus status ;
+    /** the last prefetched item */
+    private Object prefetched ;
+    /** a monitor to track the events associated with this iterator */
+    private JeIteratorMonitor monitor ;
+    /** a failure if one has occurred */
+    private Throwable fault ;
+
+    /** the Join cursor that we wrap */
+    private final JoinCursor cursor ;
+    /** the database entry primary key populated */
+    private final DatabaseEntry pk ;
+    /** the database entry data populated */
+    private final DatabaseEntry data ;
+    /** the optional entry binding to use */
+    private final EntryBinding binding ;
+    /** the secondary cursors for the JoinCursor */
+    private final SecondaryCursor[] secCursors ;
+
+
+    /**
+     * Creates a JeJoinIterator that iterates over values: db rows/records.
+     *
+     * @param cursor the underlying join cursor being wrapped
+     * @param secCursors due to a bug we need them to close em our selves
+     */
+    public JeJoinIterator( JoinCursor cursor, SecondaryCursor[] secCursors )
+            throws DatabaseException, IOException
+    {
+        this( cursor, secCursors, null, true ) ;
+    }
+
+
+    /**
+     * Creates a JeJoinIterator that iterates over primary key entries, or
+     * values.
+     *
+     * @param cursor the underlying join cursor being wrapped
+     * @param secCursors due to a bug we need them to close em our selves
+     * @param getBoth whether or not to fetch both the pk and the data - if
+     * true the data is fetched as well
+     */
+    public JeJoinIterator( JoinCursor cursor, SecondaryCursor[] secCursors,
+                       boolean getBoth )
+            throws DatabaseException, IOException
+    {
+        this( cursor, secCursors, null, getBoth ) ;
+    }
+
+
+    /**
+     * Creates a JeJoinIterator that iterates over primary key entries, values
+     * or bound object using an optional binding.
+     *
+     * @param cursor the underlying join cursor being wrapped
+     * @param secCursors due to a bug we need them to close em our selves
+     * @param binding optional binding to apply to pk or data before it is
+     * returned in the prefetch operation
+     * @param getBoth whether or not to fetch both the pk and the data - if
+     * true the data is fetched as well
+     */
+    public JeJoinIterator( JoinCursor cursor, SecondaryCursor[] secCursors,
+                       EntryBinding binding, boolean getBoth )
+            throws DatabaseException, IOException
+    {
+        this.pk = new DatabaseEntry() ;
+        this.cursor = cursor ;
+        this.secCursors = secCursors ;
+        this.monitor = new JeIteratorMonitorAdapter() ;
+        this.binding = binding ;
+
+        if ( getBoth )
+        {
+            this.data = new DatabaseEntry() ;
+        }
+        else
+        {
+            this.data = null ;
+        }
+
+        try
+        {
+            prefetched = prefetch() ;
+        }
+        catch ( DatabaseException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( IOException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( Error e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+    }
+
+
+    /**
+     * Remove is unsupported so calling this monitors the call, closes this
+     * iterator and throws an exception.
+     *
+     * @throws UnsupportedOperationException every time.
+     */
+    public final void remove()
+    {
+        UnsupportedOperationException fault ;
+
+        monitor.removeAttempted( this ) ;
+        fault = new UnsupportedOperationException() ;
+        close( fault ) ;
+
+        throw fault ;
+    }
+
+
+    /**
+     * Gets the boolean hasNext flag for this iterator.
+     *
+     * @return whether or not another data is available by calling next()
+     */
+    public final boolean hasNext()
+    {
+        return hasNext ;
+    }
+
+
+    /**
+     * Saves the last prefetched data which is returned but before returning
+     * it prefetches the next data.   Failures and succcesses are reported to
+     * the monitor.
+     *
+     * @return the next item in the iteration
+     */
+    public final Object next()
+    {
+        Object retval = prefetched ;
+
+        if ( ! hasNext )
+        {
+            throw new NoSuchElementException() ;
+        }
+
+        try
+        {
+            prefetched = prefetch() ;
+            monitor.prefetch( this, prefetched, retval ) ;
+        }
+        catch ( Exception e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this, retval ) ;
+
+            if ( e instanceof RuntimeException )
+            {
+                throw ( RuntimeException ) e ;
+            }
+        }
+        catch ( Error e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this, retval ) ;
+            throw e ;
+        }
+
+        return retval ;
+    }
+
+
+    /**
+     * Checks to see if this iterator was closed prematurely due to a failure
+     * or if it was closed by being consumed or by an intentional close call.
+     *
+     * @return true if this closed due to a failure, false otherwise
+     */
+    public final boolean hasFailed()
+    {
+        return fault != null ;
+    }
+
+
+    /**
+     * Gets the status of the last prefetch operation against a JE cursor.
+     *
+     * @return the status of the last prefetch operation
+     */
+    public final OperationStatus getStatus()
+    {
+        return status ;
+    }
+
+
+    /**
+     * Gets the failure that prematurely closed this cursor.
+     *
+     * @return the failure that prematurely closed this cursor, or null if
+     * no failures occured during cursor operation
+     */
+    public final Throwable getFault()
+    {
+        return fault ;
+    }
+
+
+    /**
+     * Gets the optional binding for this iterator.
+     *
+     * @return the optional binding for this iterator
+     */
+    public final EntryBinding getBinding()
+    {
+        return binding ;
+    }
+
+
+    /**
+     * Closes this iterator by setting hasNext flag perminantly to false and
+     * calling the cleanup method if the iterator was not closed before.
+     * Failure and success event notifications are sent via callback events
+     * to the monitor.  If any observers exist for this iterator they also are
+     * notified of the closing of this iterator.  hence
+     */
+    public final void close()
+    {
+        if ( ! hasNext )
+        {
+            return ;
+        }
+
+        hasNext = false ;
+        super.setChanged() ;
+
+        try
+        {
+            cleanup() ;
+        }
+        catch ( Exception e )
+        {
+            monitor.cleanupFailure( this, e ) ;
+            if ( e instanceof RuntimeException )
+            {
+                throw ( RuntimeException ) e ;
+            }
+        }
+        catch( Error e )
+        {
+            monitor.cleanupFailure( this, e ) ;
+            throw e ;
+        }
+
+        super.notifyObservers() ;
+        monitor.closed( this ) ;
+    }
+
+
+    /**
+     * Sets the monitor to be used by this iterator.
+     *
+     * @param monitor the monitor used for callback events
+     */
+    public final void setMonitor( JeIteratorMonitor monitor )
+    {
+        this.monitor = monitor ;
+    }
+
+
+    /**
+     * Gets whether or not this iterator fetches record data.
+     *
+     * @return whether or not this iterator fetches record data
+     */
+    public final boolean hasRecordData()
+    {
+        return data != null ;
+    }
+
+
+    // -----------------------------------------------------------------------
+    // Protected Methods
+    // -----------------------------------------------------------------------
+
+
+    /**
+     * Sets and returns the status for call chaining - closes this iterator if
+     * status is not equal to OperationStatus.SUCCESS.
+     *
+     * @param status the status to set
+     * @return the status argument for call chaining
+     */
+    private final OperationStatus setStatus( OperationStatus status )
+    {
+        this.status = status ;
+
+        if ( status != OperationStatus.SUCCESS )
+        {
+            close() ;
+        }
+
+        return this.status ;
+    }
+
+
+    /**
+     * Use this close method when failures cause this iterator to close
+     * prematurely, this sets the fault member of the class before a regular
+     * close call.
+     *
+     * @param fault a failure that caused this iterator to prematurely close
+     */
+    private final void close( Throwable fault )
+    {
+        this.fault = fault ;
+        close() ;
+    }
+
+
+    /**
+     * Concrete JeJoinIterator's must allow for item prefetching.  This method
+     * is called usually once on initialization, and once every time next() is
+     * invoked.
+     *
+     * @return the a prefetched item from the iteration
+     * @throws DatabaseException if any failures accessing the database
+     * @throws DatabaseException if any failures occur while binding
+     */
+    private final Object prefetch() throws DatabaseException, IOException
+    {
+        if ( data != null )
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( data ) ;
+            }
+
+            return data ;
+        }
+        else
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( pk ) ;
+            }
+
+            return pk ;
+        }
+    }
+
+
+    /**
+     * Cleans up by closing the JoinCursor for this iterator which in turn
+     * should close all the SecondaryCursors used but this does not seem to
+     * work.  This should be overridden to close all the SecondaryCursors
+     * used to construct the JoinCursor.
+     *
+     * @throws DatabaseException on failures while closing the join cursor
+     */
+    private final void cleanup() throws DatabaseException
+    {
+        DatabaseException e = null ;
+
+        for( int ii = 0 ; ii < secCursors.length; ii++ )
+        {
+            try
+            {
+                if ( secCursors[ii] != null )
+                {
+                    secCursors[ii].close() ;
+                }
+            }
+            catch ( DatabaseException thrown )
+            {
+                e = thrown ;
+            }
+        }
+
+        if ( cursor != null )
+        {
+            cursor.close() ;
+
+            if ( e != null )
+            {
+                throw e ;
+            }
+        }
+    }
+
+
+    /**
+     * Finalizes this JeJoinIterator by closing it.
+     */
+    public void finalize()
+    {
+        close() ;
+    }
+}

Added: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeSecondaryIterator.java
==============================================================================
--- (empty file)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/JeSecondaryIterator.java	Tue
Jun  1 11:58:37 2004
@@ -0,0 +1,433 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permission and
+ *   limitations under the License.
+ *
+ */
+package org.apache.rms.je ;
+
+
+import java.util.Observable ;
+import java.util.NoSuchElementException ;
+
+import java.io.IOException ;
+
+import com.sleepycat.je.* ;
+import com.sleepycat.bind.EntryBinding ;
+
+
+/**
+ * A JE iterator over a secondary cursor that tries to cleanup cursor resources
+ * when consumed or failures result.
+ *
+ * Goals:
+ * <ul>
+ *   <li>Implement observable pattern to track open/closed cursors</li>
+ *   <li>Keep it simple - other Iterators can wrap this one to customize</li>
+ *   <li>Return raw pk or data or objects via optional binding</li>
+ * </ul>
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory
+ * Project</a>
+ * @version $Rev$
+ */
+public class JeSecondaryIterator extends Observable
+        implements JeIterator
+{
+    /** tracks if we have another item to return */
+    private boolean hasNext = true ;
+    /** the operation status of the last prefetch operation */
+    private OperationStatus status ;
+    /** the last prefetched item */
+    private Object prefetched ;
+    /** a monitor to track the events associated with this iterator */
+    private JeIteratorMonitor monitor ;
+    /** a failure if one has occurred */
+    private Throwable fault ;
+
+    /** the Secondary cursor that we wrap */
+    private final SecondaryCursor cursor ;
+    /** the database entry primary key populated */
+    private final DatabaseEntry pk ;
+    /** the database entry data populated */
+    private final DatabaseEntry data ;
+    /** the optional entry binding to use */
+    private final EntryBinding binding ;
+
+
+    /**
+     * Creates a JeSecondaryIterator that iterates over values: db records.
+     *
+     * @param cursor the underlying cursor being wrapped
+     */
+    public JeSecondaryIterator( SecondaryCursor cursor )
+            throws DatabaseException, IOException
+    {
+        this( cursor, null, true ) ;
+    }
+
+
+    /**
+     * Creates a JeSecondaryIterator that iterates over primary key entries,
+     * or values.
+     *
+     * @param cursor the underlying cursor being wrapped
+     * @param getBoth whether or not to fetch both the pk and the data - if
+     * true the data is fetched as well
+     */
+    public JeSecondaryIterator( SecondaryCursor cursor, boolean getBoth )
+            throws DatabaseException, IOException
+    {
+        this( cursor, null, getBoth ) ;
+    }
+
+
+    /**
+     * Creates a JeJoinIterator that iterates over primary key entries, values
+     * or bound object using an optional binding.
+     *
+     * @param cursor the underlying cursor being wrapped
+     * @param binding optional binding to apply to pk or data before it is
+     * returned in the prefetch operation
+     * @param getBoth whether or not to fetch both the pk and the data - if
+     * true the data is fetched as well
+     */
+    public JeSecondaryIterator( SecondaryCursor cursor,
+                       EntryBinding binding, boolean getBoth )
+            throws DatabaseException, IOException
+    {
+        this.pk = new DatabaseEntry() ;
+        this.cursor = cursor ;
+        this.monitor = new JeIteratorMonitorAdapter() ;
+        this.binding = binding ;
+
+        if ( getBoth )
+        {
+            this.data = new DatabaseEntry() ;
+        }
+        else
+        {
+            this.data = null ;
+        }
+
+        try
+        {
+            prefetched = prefetch() ;
+        }
+        catch ( DatabaseException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( IOException e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+        catch ( Error e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this ) ;
+            throw e ;
+        }
+    }
+
+
+    /**
+     * Remove is unsupported so calling this monitors the call, closes this
+     * iterator and throws an exception.
+     *
+     * @throws UnsupportedOperationException every time.
+     */
+    public final void remove()
+    {
+        UnsupportedOperationException fault ;
+
+        monitor.removeAttempted( this ) ;
+        fault = new UnsupportedOperationException() ;
+        close( fault ) ;
+
+        throw fault ;
+    }
+
+
+    /**
+     * Gets the boolean hasNext flag for this iterator.
+     *
+     * @return whether or not another data is available by calling next()
+     */
+    public final boolean hasNext()
+    {
+        return hasNext ;
+    }
+
+
+    /**
+     * Saves the last prefetched data which is returned but before returning
+     * it prefetches the next data.   Failures and succcesses are reported to
+     * the monitor.
+     *
+     * @return the next item in the iteration
+     */
+    public final Object next()
+    {
+        Object retval = prefetched ;
+
+        if ( ! hasNext )
+        {
+            throw new NoSuchElementException() ;
+        }
+
+        try
+        {
+            prefetched = prefetch() ;
+            monitor.prefetch( this, prefetched, retval ) ;
+        }
+        catch ( Exception e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this, retval ) ;
+
+            if ( e instanceof RuntimeException )
+            {
+                throw ( RuntimeException ) e ;
+            }
+        }
+        catch ( Error e )
+        {
+            close( e ) ;
+            monitor.prefetchFailure( this, retval ) ;
+            throw e ;
+        }
+
+        return retval ;
+    }
+
+
+    /**
+     * Checks to see if this iterator was closed prematurely due to a failure
+     * or if it was closed by being consumed or by an intentional close call.
+     *
+     * @return true if this closed due to a failure, false otherwise
+     */
+    public final boolean hasFailed()
+    {
+        return fault != null ;
+    }
+
+
+    /**
+     * Gets the status of the last prefetch operation against a JE cursor.
+     *
+     * @return the status of the last prefetch operation
+     */
+    public final OperationStatus getStatus()
+    {
+        return status ;
+    }
+
+
+    /**
+     * Gets the failure that prematurely closed this cursor.
+     *
+     * @return the failure that prematurely closed this cursor, or null if
+     * no failures occured during cursor operation
+     */
+    public final Throwable getFault()
+    {
+        return fault ;
+    }
+
+
+    /**
+     * Gets the optional binding for this iterator.
+     *
+     * @return the optional binding for this iterator
+     */
+    public final EntryBinding getBinding()
+    {
+        return binding ;
+    }
+
+
+    /**
+     * Closes this iterator by setting hasNext flag perminantly to false and
+     * calling the cleanup method if the iterator was not closed before.
+     * Failure and success event notifications are sent via callback events
+     * to the monitor.  If any observers exist for this iterator they also are
+     * notified of the closing of this iterator.  hence
+     */
+    public final void close()
+    {
+        if ( ! hasNext )
+        {
+            return ;
+        }
+
+        hasNext = false ;
+        super.setChanged() ;
+
+        try
+        {
+            cleanup() ;
+        }
+        catch ( Exception e )
+        {
+            monitor.cleanupFailure( this, e ) ;
+            if ( e instanceof RuntimeException )
+            {
+                throw ( RuntimeException ) e ;
+            }
+        }
+        catch( Error e )
+        {
+            monitor.cleanupFailure( this, e ) ;
+            throw e ;
+        }
+
+        super.notifyObservers() ;
+        monitor.closed( this ) ;
+    }
+
+
+    /**
+     * Sets the monitor to be used by this iterator.
+     *
+     * @param monitor the monitor used for callback events
+     */
+    public final void setMonitor( JeIteratorMonitor monitor )
+    {
+        this.monitor = monitor ;
+    }
+
+
+    /**
+     * Gets whether or not this iterator fetches record data.
+     *
+     * @return whether or not this iterator fetches record data
+     */
+    public final boolean hasRecordData()
+    {
+        return data != null ;
+    }
+
+
+    // -----------------------------------------------------------------------
+    // Protected Methods
+    // -----------------------------------------------------------------------
+
+
+    /**
+     * Sets and returns the status for call chaining - closes this iterator if
+     * status is not equal to OperationStatus.SUCCESS.
+     *
+     * @param status the status to set
+     * @return the status argument for call chaining
+     */
+    private final OperationStatus setStatus( OperationStatus status )
+    {
+        this.status = status ;
+
+        if ( status != OperationStatus.SUCCESS )
+        {
+            close() ;
+        }
+
+        return this.status ;
+    }
+
+
+    /**
+     * Use this close method when failures cause this iterator to close
+     * prematurely, this sets the fault member of the class before a regular
+     * close call.
+     *
+     * @param fault a failure that caused this iterator to prematurely close
+     */
+    private final void close( Throwable fault )
+    {
+        this.fault = fault ;
+        close() ;
+    }
+
+
+    /**
+     * Concrete JeJoinIterator's must allow for item prefetching.  This method
+     * is called usually once on initialization, and once every time next() is
+     * invoked.
+     *
+     * @return the a prefetched item from the iteration
+     * @throws com.sleepycat.je.DatabaseException if any failures accessing the database
+     * @throws com.sleepycat.je.DatabaseException if any failures occur while binding
+     */
+    private final Object prefetch() throws DatabaseException, IOException
+    {
+        if ( data != null )
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( data ) ;
+            }
+
+            return data ;
+        }
+        else
+        {
+            setStatus( cursor.getNext( pk, data, LockMode.DEFAULT ) ) ;
+
+            if ( binding != null )
+            {
+                return binding.entryToObject( pk ) ;
+            }
+
+            return pk ;
+        }
+    }
+
+
+    /**
+     * Cleans up by closing the JoinCursor for this iterator which in turn
+     * should close all the SecondaryCursors used but this does not seem to
+     * work.  This should be overridden to close all the SecondaryCursors
+     * used to construct the JoinCursor.
+     *
+     * @throws com.sleepycat.je.DatabaseException on failures while closing the join cursor
+     */
+    private final void cleanup() throws DatabaseException
+    {
+        DatabaseException e = null ;
+
+        if ( cursor != null )
+        {
+            cursor.close() ;
+
+            if ( e != null )
+            {
+                throw e ;
+            }
+        }
+    }
+
+
+    /**
+     * Finalizes this JeJoinIterator by closing it.
+     */
+    public void finalize()
+    {
+        close() ;
+    }
+}

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java
(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileDAO.java
Tue Jun  1 11:58:37 2004
@@ -20,23 +20,23 @@
 import org.apache.rms.Profile ;
 import org.apache.rms.Application ;
 import org.apache.rms.RmsException ;
-import org.apache.rms.spi.ProfileDAO;
-import org.apache.rms.spi.ProfileDAOMonitor;
-import org.apache.rms.spi.ProfileDAOMonitorAdapter;
-import org.apache.rms.spi.ProfileRoleLinkDAO;
+import org.apache.rms.spi.ProfileDAO ;
+import org.apache.rms.spi.ProfileDAOMonitor ;
+import org.apache.rms.spi.ProfileDAOMonitorAdapter ;
+import org.apache.rms.spi.ProfileRoleLinkDAO ;
+
+import org.apache.rms.je.JeUtils ;
 import org.apache.rms.je.JeRmsException ;
-import org.apache.rms.je.JeUtils;
-import org.apache.rms.je.JeIterator;
 import org.apache.rms.je.sequence.Sequence ;
 
 import org.apache.commons.lang.Validate ;
 import org.apache.commons.lang.NotImplementedException ;
-import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.EmptyIterator ;
 
 import java.util.List ;
 import java.util.Iterator ;
+import java.io.IOException ;
 import java.io.UnsupportedEncodingException ;
-import java.io.IOException;
 
 import com.sleepycat.je.* ;
 
@@ -342,7 +342,6 @@
     public Iterator listUserNames( String appName ) throws RmsException
     {
         OperationStatus status = null ;
-        DatabaseEntry key = new DatabaseEntry() ;
         DatabaseEntry value = new DatabaseEntry() ;
         DatabaseEntry appNameKey = new DatabaseEntry() ;
 
@@ -376,7 +375,8 @@
             throw new RmsException( e ) ;
         }
 
-        return new JeIterator() ;
+        // return new JeJoinIterator() ;
+        throw new NotImplementedException( "STUB" ) ;
     }
 
 

Modified: incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
==============================================================================
--- incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
(original)
+++ incubator/directory/rms/trunk/je/src/java/org/apache/rms/je/profile/JeProfileRoleLinkDAO.java
Tue Jun  1 11:58:37 2004
@@ -22,7 +22,7 @@
 import org.apache.rms.spi.ProfileRoleLinkDAO;
 import org.apache.rms.spi.ProfileRoleLinkDAOMonitor;
 import org.apache.rms.spi.ProfileRoleLinkDAOMonitorAdapter;
-import org.apache.rms.je.JeIterator ;
+import org.apache.rms.je.JeJoinIterator ;
 import org.apache.rms.je.JeRmsException ;
 import org.apache.rms.je.LoggingJeIteratorMonitor;
 import org.apache.rms.je.sequence.Sequence ;
@@ -584,7 +584,7 @@
             SecondaryCursor [] secCursors = { appNameCursor, userNameCursor } ;
             cursor = db.join( secCursors, null ) ;
 
-            JeIterator iterator = new JeIterator( cursor, secCursors,
+            JeJoinIterator iterator = new JeJoinIterator( cursor, secCursors,
                     JeProfileRoleLinkBinding.ROLENAME_BINDING, true ) ;
             iterator.addObserver( this ) ;
             openIterators.add( iterator ) ;
@@ -688,7 +688,7 @@
 
             SecondaryCursor [] secCursors = { appNameCursor, roleNameCursor } ;
             cursor = db.join( secCursors, null ) ;
-            JeIterator iterator = new JeIterator( cursor, secCursors,
+            JeJoinIterator iterator = new JeJoinIterator( cursor, secCursors,
                     JeProfileRoleLinkBinding.USERNAME_BINDING, true ) ;
             iterator.addObserver( this ) ;
             openIterators.add( iterator ) ;
@@ -724,9 +724,9 @@
      */
     public void close( Iterator list )
     {
-        if ( list instanceof JeIterator )
+        if ( list instanceof JeJoinIterator )
         {
-            ( ( JeIterator ) list ).close() ;
+            ( ( JeJoinIterator ) list ).close() ;
         }
     }
 
@@ -933,7 +933,7 @@
      */
     public void update( Observable o, Object arg )
     {
-        if ( o instanceof JeIterator )
+        if ( o instanceof JeJoinIterator )
         {
             openIterators.remove( o ) ;
         }

Modified: incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitor.java
==============================================================================
--- incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitor.java	(original)
+++ incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitor.java	Tue
Jun  1 11:58:37 2004
@@ -17,6 +17,9 @@
 package org.apache.rms.spi ;
 
 
+import java.io.UnsupportedEncodingException;
+
+
 /**
  * The monitor interface for a Profile data access object.
  * 
@@ -60,5 +63,9 @@
 
     void constraintViolationOnDelete( ProfileDAO dao, String appName,
                                       String userName ) ;
+
+
+    void failedOnListUserNames( ProfileDAO dao, String appName,
+                                Throwable fault ) ;
 
 }

Modified: incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitorAdapter.java
==============================================================================
--- incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitorAdapter.java
(original)
+++ incubator/directory/rms/trunk/spi/src/java/org/apache/rms/spi/ProfileDAOMonitorAdapter.java
Tue Jun  1 11:58:37 2004
@@ -112,4 +112,14 @@
                                              String userName )
     {
     }
+
+
+    public void failedOnListUserNames( ProfileDAO dao, String appName,
+                                       Throwable fault )
+    {
+        if ( fault != null )
+        {
+            fault.printStackTrace() ;
+        }
+    }
 }

Mime
View raw message