directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From seelm...@apache.org
Subject svn commit: r902620 [2/6] - in /directory/sandbox/seelmann/hbase-partition: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/server/ src/main/java/org/a...
Date Sun, 24 Jan 2010 19:04:39 GMT
Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseSubLevelIndexCursor.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseSubLevelIndexCursor.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseSubLevelIndexCursor.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseSubLevelIndexCursor.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,313 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.cursor;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.SingleColumnQualifierFilter;
+import org.apache.directory.server.core.partition.hbase.Utils;
+import org.apache.directory.server.core.partition.hbase.table.HBaseMasterTable;
+import org.apache.directory.server.xdbm.ForwardIndexEntry;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.LeafNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.BinaryComparator;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.WritableByteArrayComparable;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.FilterList.Operator;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+/**
+ * HBase specific implementation of the sub-level index cursor.
+ * There is no special sub-level index table, but the tree table is used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseSubLevelIndexCursor extends BaseHBaseIndexCursor<Long>
+{
+    /** The entry ID of the search base. */
+    private Long baseId;
+
+    /** The filter to apply while scanning. */
+    private ExprNode filter;
+
+    /** Contains entry IDs which needs to be scanned for children. */
+    private List<Long> parentIds;
+
+
+    public HBaseSubLevelIndexCursor( Long baseId, HBaseStore store )
+    {
+        super( store );
+        this.baseId = baseId;
+    }
+
+
+    public HBaseSubLevelIndexCursor( Long baseId, ExprNode filter, HBaseStore store )
+    {
+        this( baseId, store );
+        this.filter = filter;
+    }
+
+
+    @Override
+    public void reset()
+    {
+        parentIds = null;
+        super.reset();
+    }
+
+
+    private void nextScanner() throws Exception
+    {
+        if ( scanner != null )
+        {
+            scanner.close();
+            scanner = null;
+            iterator = null;
+        }
+
+        if ( parentIds != null && !parentIds.isEmpty() )
+        {
+            // create a scanner over all direct children of the parent
+            Long key = parentIds.remove( 0 );
+            byte[] start = Bytes.toBytes( key );
+            byte[] stop = Bytes.toBytes( key + 1 );
+            Scan scan = new Scan( start, stop );
+            scan.addFamily( HBaseMasterTable.TREE_INFO_FAMILY );
+            scan.addFamily( HBaseMasterTable.NORM_ATTRIBUTES_FAMILY );
+
+            Filter mainFilter = getFilter( filter, store );
+            if ( mainFilter != null )
+            {
+                // we need to get two kind of entries:
+                // - all entries that match the filter
+                // - all entries that have an children: one-level count > 0
+                // hence we use an or filter here
+                FilterList filterList = new FilterList( Operator.MUST_PASS_ONE );
+                filterList.addFilter( mainFilter );
+                BinaryComparator comparator = new BinaryComparator( HBaseMasterTable.ONE_LEVEL_COUNT_QUALIFIER );
+                SingleColumnQualifierFilter countFilter = new SingleColumnQualifierFilter(
+                    HBaseMasterTable.TREE_INFO_FAMILY, CompareOp.EQUAL, comparator );
+                //SingleColumnValueFilter countFilter = new SingleColumnValueFilter( HBaseMasterTable.TREE_INFO_FAMILY, HBaseMasterTable.ONE_LEVEL_COUNT_QUALIFIER, CompareOp.GREATER, Bytes.toBytes( 0L ) );
+                filterList.addFilter( countFilter );
+                scan.setFilter( filterList );
+            }
+
+            scanner = store.getMasterTable().getScanner( scan );
+            iterator = scanner.iterator();
+        }
+    }
+
+
+    public boolean doNext() throws Exception
+    {
+        if ( scanner == null && currentEntry == null )
+        {
+            // we are beforeFirst, the first result is the search base itself
+            // TODO: check if the base entry matches the filter criteria
+            fetchEntry( baseId, null );
+
+            // Add the base to the list of entry IDs which needs to be scanned.
+            // We don't need to scan for children if the entry doesn't have children.
+            if ( store.getChildCount( baseId ) > 0 )
+            {
+                parentIds = new ArrayList<Long>();
+                parentIds.add( baseId );
+            }
+
+            return true;
+        }
+        else
+        {
+            if ( scanner == null )
+            {
+                nextScanner();
+            }
+
+            // in case the the scanner doesn't return a result we take the next scanner
+            while ( iterator != null && !iterator.hasNext() )
+            {
+                nextScanner();
+            }
+
+            if ( iterator != null && iterator.hasNext() )
+            {
+                Result next = iterator.next();
+                byte[] id = next.getValue( HBaseMasterTable.TREE_INFO_FAMILY, HBaseMasterTable.ID_QUALIFIER );
+                byte[] oneLevelCount = next.getValue( HBaseMasterTable.TREE_INFO_FAMILY,
+                    HBaseMasterTable.ONE_LEVEL_COUNT_QUALIFIER );
+
+                // Add the next ID to the list of entry IDs which needs to be scanned.
+                // We don't need to scan for children if the entry doesn't have children.
+                if ( oneLevelCount != null && Bytes.toLong( oneLevelCount ) > 0L )
+                {
+                    parentIds.add( Bytes.toLong( id ) );
+                }
+
+                // TODO: use evaluator on normAttributes to evaluate if entry matches the filter 
+                fetchEntry( Bytes.toLong( id ), next );
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    private void fetchEntry( Long id, Result next ) throws Exception
+    {
+        //System.out.println("fetchEntry " + Bytes.toLong( id ));
+        currentEntry = new ForwardIndexEntry<Long, ServerEntry>();
+        currentEntry.setId( id );
+        currentEntry.setValue( baseId );
+        if ( filter != null && next != null )
+        {
+            //            //ServerEntry entry = store.getMasterTable().convertToServerEntry( id, next );
+            //            ServerEntry entry = store.lookup( id );
+            //            currentEntry.setObject( entry );
+        }
+    }
+
+
+    static Filter getFilter( ExprNode node, HBaseStore store ) throws Exception
+    {
+        if ( node != null )
+        {
+            try
+            {
+                return buildFilter( node, store );
+            }
+            catch ( IllegalStateException e )
+            {
+                // can't handle filter
+                System.out.println( "Filter too complex: " + node );
+                return null;
+            }
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    private static Filter buildFilter( ExprNode node, HBaseStore store ) throws Exception
+    {
+        if ( node.isLeaf() )
+        {
+            String attribute = ( ( LeafNode ) node ).getAttribute();
+            String oid = store.getSchemaManager().getAttributeTypeRegistry().getOidByName( attribute );
+            String quotedOid = Pattern.quote( oid );
+
+            CompareOp compareOp;
+            switch ( node.getAssertionType() )
+            {
+                case SUBSTRING:
+                case PRESENCE:
+                case APPROXIMATE:
+                case EQUALITY:
+                    compareOp = CompareOp.EQUAL;
+                    break;
+                case GREATEREQ:
+                    compareOp = CompareOp.GREATER_OR_EQUAL;
+                    break;
+                case LESSEQ:
+                    compareOp = CompareOp.LESS_OR_EQUAL;
+                    break;
+                default:
+                    throw new IllegalStateException( "Unexpected leaf assertion type: " + node.getAssertionType() );
+            }
+
+            WritableByteArrayComparable comparator;
+            switch ( node.getAssertionType() )
+            {
+                case EQUALITY:
+                    String value = ( ( EqualityNode<?> ) node ).getValue().getString();
+                    comparator = new BinaryComparator( Bytes.toBytes( oid + HBaseMasterTable.NORM_ATTRIBUTE_DELIMITER
+                        + value ) );
+                    break;
+                case PRESENCE:
+                    comparator = new RegexStringComparator( "^" + quotedOid + HBaseMasterTable.NORM_ATTRIBUTE_DELIMITER
+                        + ".*" );
+                    break;
+                case SUBSTRING:
+                    String valuePattern = Utils.getValuePattern( ( SubstringNode ) node, store );
+                    comparator = new RegexStringComparator( "^" + quotedOid + HBaseMasterTable.NORM_ATTRIBUTE_DELIMITER
+                        + valuePattern );
+                    break;
+                default:
+                    throw new IllegalStateException( "Unexpected leaf assertion type: " + node.getAssertionType() );
+            }
+
+            return new SingleColumnQualifierFilter( HBaseMasterTable.NORM_ATTRIBUTES_FAMILY, compareOp, comparator );
+        }
+        else
+        {
+            switch ( node.getAssertionType() )
+            {
+                case OR:
+                    return buildOrFilter( ( OrNode ) node, store );
+                case AND:
+                    //return buildAndCursor( ( AndNode ) node );
+                case NOT:
+                    //return new SkipFilter( buildFilter( ( ( NotNode ) node ).getFirstChild() ) );
+                default:
+                    throw new IllegalStateException( "Unexpected non-leaf assertion type: " + node.getAssertionType() );
+            }
+        }
+    }
+
+
+    //    private Filter buildAndCursor( AndNode node ) throws Exception
+    //    {
+    //        FilterList orList = new FilterList( Operator.MUST_PASS_ALL );
+    //        for ( ExprNode child : node.getChildren() )
+    //        {
+    //            orList.addFilter( buildFilter(child) );
+    //        }
+    //        return orList;
+    //    }
+    //
+    //
+    private static Filter buildOrFilter( OrNode node, HBaseStore store ) throws Exception
+    {
+        FilterList orList = new FilterList( Operator.MUST_PASS_ONE );
+        for ( ExprNode child : node.getChildren() )
+        {
+            orList.addFilter( buildFilter( child, store ) );
+        }
+        return orList;
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserColumnIndexCursor.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserColumnIndexCursor.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserColumnIndexCursor.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserColumnIndexCursor.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,246 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.cursor;
+
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.Utils;
+import org.apache.directory.server.core.partition.hbase.table.HBaseColumnIndexTable;
+import org.apache.directory.server.core.partition.hbase.table.HBaseIndexTable;
+import org.apache.directory.server.xdbm.ForwardIndexEntry;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.RowFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+
+
+/**
+ * HBase specific implementation of an user index cursor that reads
+ * candidates from treeInfo column family.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseUserColumnIndexCursor extends HBaseUserIndexCursor
+{
+
+    private final HBaseColumnIndexTable indexTable;
+    private Iterator<Long> candidates;
+
+
+    // TODO: count for substring, gt, lt
+
+    public HBaseUserColumnIndexCursor( String attributeTypeOid, Object value, HBaseColumnIndexTable indexTable,
+        HBaseStore store )
+    {
+        super( attributeTypeOid, value, store );
+        this.indexTable = indexTable;
+    }
+
+
+    public HBaseUserColumnIndexCursor( String attributeTypeOid, HBaseColumnIndexTable indexTable, HBaseStore store )
+    {
+        super( attributeTypeOid, store );
+        this.indexTable = indexTable;
+    }
+
+
+    public HBaseUserColumnIndexCursor( String attributeTypeOid, SubstringNode node, HBaseColumnIndexTable indexTable,
+        HBaseStore store ) throws Exception
+    {
+        super( attributeTypeOid, node, store );
+        this.indexTable = indexTable;
+    }
+
+
+    @Override
+    public void reset()
+    {
+        candidates = null;
+        super.reset();
+    }
+
+
+    @Override
+    public boolean doNext() throws Exception
+    {
+        if ( candidates == null )
+        {
+            nextCandidates();
+        }
+        while ( candidates != null && !candidates.hasNext() )
+        {
+            nextCandidates();
+        }
+
+        if ( candidates != null && candidates.hasNext() )
+        {
+            Long next = candidates.next();
+            currentEntry = new ForwardIndexEntry<Object, ServerEntry>();
+            currentEntry.setId( next );
+            currentEntry.setValue( value );
+
+            return true;
+        }
+
+        return false;
+    }
+
+
+    private void nextCandidates() throws Exception
+    {
+        if ( scanner == null )
+        {
+            byte[] start;
+            byte[] stop;
+            Pattern rowFilterPattern;
+
+            if ( value != null && exactValue )
+            {
+                /*
+                 * this case is relevant for equal filters, e.g. (cn=test)
+                 */
+                candidates = indexTable.getColumnCandidates( value ).iterator();
+
+                // prepare an empty scanner and iterator for the next call
+                scanner = new ResultScanner()
+                {
+                    //Object candidates = indexTable.getColumnCandidates( value ).iterator();
+                    private Result[] EMPTY = new Result[0];
+
+
+                    @SuppressWarnings("unchecked")
+                    public Iterator<Result> iterator()
+                    {
+                        return EmptyIterator.INSTANCE;
+                    }
+
+
+                    public Result[] next( int arg0 ) throws IOException
+                    {
+                        return EMPTY;
+                    }
+
+
+                    public Result next() throws IOException
+                    {
+                        return null;
+                    }
+
+
+                    public void close()
+                    {
+                    }
+                };
+                iterator = scanner.iterator();
+                return;
+            }
+            else if ( node != null )
+            {
+                if ( node.getInitial() != null )
+                {
+                    /*
+                     * this case is relevant for substring filters with an initial pattern, e.g. (cn=test*)
+                     * - row filter is "^#test.*$" 
+                     */
+                    start = indexTable.getScanKey( node.getInitial(), null );
+                    stop = indexTable.getScanKey( node.getInitial(), HBaseIndexTable.VALUE_SCAN_STOP );
+                    rowFilterPattern = Pattern.compile( "^#" + Utils.getValuePattern( node, store ) + "$" );
+                }
+                else
+                {
+                    /*
+                     * this case is relevant for substring filters w/o an initial pattern, e.g. (cn=*test*) 
+                     * unfortunately we need to scan the whole index, but can set a row filter
+                     * - row filter is "^#.*test.*$" 
+                     */
+                    start = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_START, null );
+                    stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                    rowFilterPattern = Pattern.compile( "^#" + Utils.getValuePattern( node, store ) + "$" );
+                }
+            }
+            else if ( value != null )
+            {
+                /*
+                 * this case is relevant for greater than filters (the start value is set by before(IndexEntry)), e.g. (cn>=test)
+                 * - start row is "#test"
+                 * - stop row is "#0xFF"
+                 */
+                start = indexTable.getScanKey( value, null );
+                stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                // TODO: is it possible to use the LdapComparator for the row filter?
+                rowFilterPattern = null;
+            }
+            else
+            {
+                /*
+                 * this case is relevant for less than filters, e.g. (cn<=test)
+                 * unfortunately we need to scan the whole index
+                 * - start row is "#0x00"
+                 * - stop row is "#0xFF"
+                 */
+                start = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_START, null );
+                stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                // TODO: is it possible to use the LdapComparator for the row filter?
+                rowFilterPattern = null;
+            }
+
+            Filter filter = null;
+            if ( rowFilterPattern != null )
+            {
+                RegexStringComparator comparator = new RegexStringComparator( rowFilterPattern.toString() );
+                RowFilter rowFilter = new RowFilter( CompareOp.EQUAL, comparator );
+                filter = rowFilter;
+            }
+
+            Scan scan = new Scan( start, stop );
+            scan.addFamily( HBaseIndexTable.INFO_FAMILY );
+            scan.setFilter( filter );
+
+            // seems to be a performance boost when less rows are matching...
+            scan.setCaching( 1000 );
+
+            scanner = indexTable.getScanner( scan );
+            iterator = scanner.iterator();
+        }
+
+        if ( iterator.hasNext() )
+        {
+            Result result = iterator.next();
+            value = indexTable.getValueFromCountKey( result.getRow() );
+            candidates = indexTable.getColumnCandidates( result ).iterator();
+        }
+        else
+        {
+            candidates = null;
+        }
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexCursor.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexCursor.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexCursor.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexCursor.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,77 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.cursor;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.xdbm.IndexEntry;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+
+
+/**
+ * Base implementation of an HBase specific user index cursor.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class HBaseUserIndexCursor extends BaseHBaseIndexCursor<Object>
+{
+    protected String attributeTypeOid;
+    protected Object value;
+    protected boolean exactValue;
+    protected SubstringNode node;
+
+
+    public HBaseUserIndexCursor( String attributeTypeOid, Object value, HBaseStore store )
+    {
+        super( store );
+        this.attributeTypeOid = attributeTypeOid;
+        this.value = value;
+        this.exactValue = true;
+    }
+
+
+    public HBaseUserIndexCursor( String attributeTypeOid, HBaseStore store )
+    {
+        super( store );
+        this.attributeTypeOid = attributeTypeOid;
+        this.value = null;
+        this.exactValue = false;
+    }
+
+
+    public HBaseUserIndexCursor( String attributeTypeOid, SubstringNode node, HBaseStore store ) throws Exception
+    {
+        super( store );
+        this.attributeTypeOid = attributeTypeOid;
+        this.node = node;
+        this.exactValue = false;
+    }
+
+
+    @Override
+    public void before( IndexEntry<Object, ServerEntry> element ) throws Exception
+    {
+        value = element.getValue();
+        reset();
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexReverseCursor.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexReverseCursor.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexReverseCursor.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserIndexReverseCursor.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,105 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.cursor;
+
+
+import java.util.Iterator;
+import java.util.NavigableMap;
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.table.HBaseMasterTable;
+import org.apache.directory.server.xdbm.ForwardIndexEntry;
+import org.apache.directory.server.xdbm.IndexEntry;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+/**
+ * HBase specific implementation of an reverse user index cursor. As HBase
+ * tables only allow forward lookups (row key -&gt; value) the reverse cursor
+ * uses the master and tree table to lookup attributes for an entry ID.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseUserIndexReverseCursor extends AbstractHBaseIndexCursor<Object, ServerEntry>
+{
+    private String attributeTypeOid;
+    private Long id;
+    private HBaseStore store;
+
+    private NavigableMap<byte[], byte[]> attributeMap;
+    private Iterator<byte[]> attributeIterator;
+    private IndexEntry<Object, ServerEntry> currentEntry;
+
+
+    public HBaseUserIndexReverseCursor( String attributeTypeOid, Long id, HBaseStore store )
+    {
+        this.attributeTypeOid = attributeTypeOid;
+        this.id = id;
+        this.store = store;
+    }
+
+
+    @Override
+    public IndexEntry<Object, ServerEntry> get() throws Exception
+    {
+        return currentEntry;
+    }
+
+
+    @Override
+    public boolean next() throws Exception
+    {
+        if ( attributeMap == null )
+        {
+            attributeMap = store.getMasterTable().fetchNormAttributes( id );
+            attributeIterator = attributeMap.keySet().iterator();
+        }
+
+        while ( attributeIterator != null && attributeIterator.hasNext() )
+        {
+            byte[] next = attributeIterator.next();
+            String oid = null;
+            byte[] value = null;
+            for ( int i = 0; i < next.length; i++ )
+            {
+                if ( next[i] == HBaseMasterTable.NORM_ATTRIBUTE_DELIMITER )
+                {
+                    oid = Bytes.toString( Bytes.head( next, i ) );
+                    value = Bytes.tail( next, next.length - i - 1 );
+                    break;
+                }
+            }
+
+            if ( oid != null && oid.equals( attributeTypeOid ) )
+            {
+                currentEntry = new ForwardIndexEntry<Object, ServerEntry>();
+                currentEntry.setId( id );
+                AttributeType at = store.getSchemaManager().getAttributeTypeRegistry().lookup( attributeTypeOid );
+                currentEntry.setValue( at.getSyntax().isHumanReadable() ? Bytes.toString( value ) : value );
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserRowIndexCursor.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserRowIndexCursor.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserRowIndexCursor.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/cursor/HBaseUserRowIndexCursor.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,194 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.cursor;
+
+
+import java.util.regex.Pattern;
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.Utils;
+import org.apache.directory.server.core.partition.hbase.table.HBaseIndexTable;
+import org.apache.directory.server.core.partition.hbase.table.HBaseRowIndexTable;
+import org.apache.directory.server.xdbm.ForwardIndexEntry;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.RowFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+/**
+ * HBase specific implementation of an user index cursor that reads
+ * candidates from the row key.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseUserRowIndexCursor extends HBaseUserIndexCursor
+{
+
+    private final HBaseRowIndexTable indexTable;
+
+
+    public HBaseUserRowIndexCursor( String attributeTypeOid, Object value, HBaseRowIndexTable indexTable,
+        HBaseStore store )
+    {
+        super( attributeTypeOid, value, store );
+        this.indexTable = indexTable;
+    }
+
+
+    public HBaseUserRowIndexCursor( String attributeTypeOid, HBaseRowIndexTable indexTable, HBaseStore store )
+    {
+        super( attributeTypeOid, store );
+        this.indexTable = indexTable;
+    }
+
+
+    public HBaseUserRowIndexCursor( String attributeTypeOid, SubstringNode node, HBaseRowIndexTable indexTable,
+        HBaseStore store ) throws Exception
+    {
+        super( attributeTypeOid, node, store );
+        this.indexTable = indexTable;
+    }
+
+
+    @Override
+    public boolean doNext() throws Exception
+    {
+        if ( scanner == null )
+        {
+            byte[] start;
+            byte[] stop;
+            Pattern rowFilterPattern;
+
+            if ( value != null && exactValue )
+            {
+                /*
+                 * this case is relevant for equal filters, e.g. (cn=test)
+                 * we exactly set the bound of the scanner:
+                 * - start row is "=test0x00"
+                 * - stop row is "=test0xFF"
+                 * - row filter is "^=test[A-Za-z0-9+/=]{12}$" 
+                 */
+                start = indexTable.getScanKey( value, HBaseIndexTable.VALUE_SCAN_START );
+                stop = indexTable.getScanKey( value, HBaseIndexTable.VALUE_SCAN_STOP );
+                rowFilterPattern = Pattern.compile( "^=" + Pattern.quote( "" + value ) + "[A-Za-z0-9+/=]{12}$" );
+                //rowFilterPattern = null;
+            }
+            else if ( node != null )
+            {
+                if ( node.getInitial() != null )
+                {
+                    /*
+                     * this case is relevant for substring filters with an initial pattern, e.g. (cn=test*)
+                     * - start row is "=test0x00"
+                     * - stop row is "=test0xFF"
+                     * - row filter is "^=test.*[A-Za-z0-9+/=]{12}$" 
+                     */
+                    start = indexTable.getScanKey( node.getInitial(), HBaseIndexTable.VALUE_SCAN_START );
+                    stop = indexTable.getScanKey( node.getInitial(), HBaseIndexTable.VALUE_SCAN_STOP );
+                    rowFilterPattern = Pattern.compile( "^=" + Utils.getValuePattern( node, store )
+                        + "[A-Za-z0-9+/=]{12}$" );
+                }
+                else
+                {
+                    /*
+                     * this case is relevant for substring filters w/o an initial pattern, e.g. (cn=*test*) 
+                     * unfortunately we need to scan the whole index, but can set a row filter
+                     * - start row is "=0x00"
+                     * - stop row is "=0xFF"
+                     * - row filter is "^=.*test.*[A-Za-z0-9+/=]{12}$" 
+                     */
+                    start = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_START, null );
+                    stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                    rowFilterPattern = Pattern.compile( "^=" + Utils.getValuePattern( node, store )
+                        + "[A-Za-z0-9+/=]{12}$" );
+                }
+            }
+            else if ( value != null )
+            {
+                /*
+                 * this case is relevant for greater than filters (the start value is set by before(IndexEntry)), e.g. (cn>=test)
+                 * - start row is "=test0x00"
+                 * - stop row is "=0xFF"
+                 */
+                start = indexTable.getScanKey( value, HBaseIndexTable.VALUE_SCAN_START );
+                stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                // TODO: is it possible to use the LdapComparator for the row filter?
+                rowFilterPattern = null;
+            }
+            else
+            {
+                /*
+                 * this case is relevant for less than filters, e.g. (cn<=test)
+                 * unfortunately we need to scan the whole index
+                 * - start row is "=0x00"
+                 * - stop row is "=0xFF"
+                 */
+                start = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_START, null );
+                stop = indexTable.getScanKey( HBaseIndexTable.FULL_SCAN_STOP, null );
+                // TODO: is it possible to use the LdapComparator for the row filter?
+                rowFilterPattern = null;
+            }
+
+            Filter filter = null;
+            if ( rowFilterPattern != null )
+            {
+                RegexStringComparator comparator = new RegexStringComparator( rowFilterPattern.toString() );
+                RowFilter rowFilter = new RowFilter( CompareOp.EQUAL, comparator );
+                filter = rowFilter;
+            }
+
+            Scan scan = new Scan( start, stop );
+            scan.addFamily( HBaseIndexTable.INFO_FAMILY );
+            scan.setFilter( filter );
+
+            // seems to be a performance boost when less rows are matching...
+            scan.setCaching( 1000 );
+
+            scanner = indexTable.getScanner( scan );
+            iterator = scanner.iterator();
+        }
+
+        while ( iterator.hasNext() )
+        {
+            Result next = iterator.next();
+            //byte[] row = next.getRow();
+            Object value = indexTable.getValueFromEqualsKey( next.getRow() );
+            if ( value != null )
+            {
+                byte[] id = next.getValue( HBaseIndexTable.INFO_FAMILY, HBaseIndexTable.ID_QUALIFIER );
+
+                currentEntry = new ForwardIndexEntry<Object, ServerEntry>();
+                currentEntry.setId( Bytes.toLong( id ) );
+                currentEntry.setValue( value );
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/AbstractHBaseIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/AbstractHBaseIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/AbstractHBaseIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/AbstractHBaseIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,265 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import java.io.File;
+
+import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+
+
+/**
+ * Abstract implementation if an {@link Index} that throws an 
+ * {@link UnsupportedOperationException} for each operation.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class AbstractHBaseIndex<K, O> implements Index<K, O>
+{
+
+    private int cacheSize;
+
+
+    public void add( K attrVal, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public int count() throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public int count( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void drop( Long entryId ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void drop( K attrVal, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forward( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forward( K attrVal, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public IndexCursor<K, O> forwardCursor() throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public IndexCursor<K, O> forwardCursor( K key ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forwardGreaterOrEq( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forwardGreaterOrEq( K attrVal, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forwardLessOrEq( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forwardLessOrEq( K attrVal, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public Long forwardLookup( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public Cursor<Long> forwardValueCursor( K key ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public AttributeType getAttribute()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public String getAttributeId()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public int getCacheSize()
+    {
+        return cacheSize;
+    }
+
+
+    public K getNormalized( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public File getWkDirPath()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public int greaterThanCount( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean isCountExact()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public int lessThanCount( K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverse( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverse( Long id, K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public IndexCursor<K, O> reverseCursor() throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public IndexCursor<K, O> reverseCursor( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverseGreaterOrEq( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverseGreaterOrEq( Long id, K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverseLessOrEq( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean reverseLessOrEq( Long id, K attrVal ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public K reverseLookup( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public Cursor<K> reverseValueCursor( Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void setAttributeId( String attributeId )
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void setCacheSize( int cacheSize )
+    {
+        this.cacheSize = cacheSize;
+    }
+
+
+    public void setWkDirPath( File wkDirPath )
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void sync() throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseAliasIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseAliasIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseAliasIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseAliasIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,48 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+
+
+/**
+ * HBase specific implementation of the alias index.
+ * 
+ * TODO: This is just a stub, needs to be implemented.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseAliasIndex extends AbstractHBaseIndex<String, ServerEntry>
+{
+
+    public void close() throws Exception
+    {
+    }
+
+
+    public String reverseLookup( Long id ) throws Exception
+    {
+        // TODO 
+        return null;
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseNdnIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseNdnIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseNdnIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseNdnIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,67 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseNdnIndexCursor;
+import org.apache.directory.server.xdbm.IndexCursor;
+
+
+/**
+ * HBase specific implementation of the ndn (normalized DN) index.
+ * There is no special ndn index table, but the master table is used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseNdnIndex extends AbstractHBaseIndex<String, ServerEntry>
+{
+
+    private HBaseStore store;
+
+
+    public HBaseNdnIndex( HBaseStore store )
+    {
+        this.store = store;
+    }
+
+
+    public void close() throws Exception
+    {
+        // TODO
+    }
+
+
+    @Override
+    public IndexCursor<String, ServerEntry> forwardCursor() throws Exception
+    {
+        return new HBaseNdnIndexCursor( store );
+    }
+
+
+    @Override
+    public IndexCursor<String, ServerEntry> reverseCursor() throws Exception
+    {
+        return new HBaseNdnIndexCursor( store );
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneAliasIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneAliasIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneAliasIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneAliasIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,58 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.xdbm.EmptyIndexCursor;
+import org.apache.directory.server.xdbm.IndexCursor;
+
+
+/**
+ * HBase specific implementation of the alias index.
+ * 
+ * TODO: This is just a stub, needs to be implemented.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseOneAliasIndex extends AbstractHBaseIndex<Long, ServerEntry>
+{
+
+    public void close() throws Exception
+    {
+    }
+
+
+    @Override
+    public boolean forward( Long attrVal, Long id ) throws Exception
+    {
+        // TODO
+        return false;
+    }
+
+
+    @Override
+    public IndexCursor<Long, ServerEntry> forwardCursor( Long key ) throws Exception
+    {
+        return new EmptyIndexCursor<Long, ServerEntry>();
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneLevelIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneLevelIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneLevelIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseOneLevelIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,84 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseOneLevelIndexCursor;
+import org.apache.directory.server.core.partition.hbase.xdbmext.IndexFilteringExtension;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+
+
+/**
+ * HBase specific implementation of the one-level index.
+ * There is no special one-level index table, but the tree table is used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseOneLevelIndex extends AbstractHBaseIndex<Long, ServerEntry> implements
+    IndexFilteringExtension<Long, ServerEntry>
+{
+
+    private HBaseStore store;
+
+
+    public HBaseOneLevelIndex( HBaseStore store )
+    {
+        this.store = store;
+    }
+
+
+    public void close() throws Exception
+    {
+    }
+
+
+    public boolean forward( Long baseId, Long id ) throws Exception
+    {
+        // check if 'id' is child of 'baseId'
+        long parentId = store.getMasterTable().fetchParentId( id );
+        return baseId == parentId;
+    }
+
+
+    @Override
+    public IndexCursor<Long, ServerEntry> forwardCursor( Long baseId ) throws Exception
+    {
+        return new HBaseOneLevelIndexCursor( baseId, store );
+    }
+
+
+    public IndexCursor<Long, ServerEntry> forwardFilteringCursor( Long baseId, ExprNode filter ) throws Exception
+    {
+        return new HBaseOneLevelIndexCursor( baseId, filter, store );
+    }
+
+
+    @Override
+    public int count( Long id ) throws Exception
+    {
+        return store.getMasterTable().getOneLevelCount( id );
+
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBasePresenceIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBasePresenceIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBasePresenceIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBasePresenceIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,76 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBasePresenceIndexCursor;
+import org.apache.directory.server.xdbm.IndexCursor;
+
+
+/**
+ * HBase specific implementation of the presence index.
+ * There is no special presence index table, but the index tables are used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBasePresenceIndex extends AbstractHBaseIndex<String, ServerEntry>
+{
+    private HBaseStore store;
+
+
+    public HBasePresenceIndex( HBaseStore store )
+    {
+        this.store = store;
+    }
+
+
+    public void close() throws Exception
+    {
+        // TODO Auto-generated method stub
+    }
+
+
+    @Override
+    public int count( String attributeType ) throws Exception
+    {
+        int count = store.getPresenceIndexTable( attributeType ).count();
+        //System.out.println(attributeType + " -> count=" + count);
+        return count;
+    }
+
+
+    @Override
+    public boolean forward( String attributeTypeOid, Long entryId ) throws Exception
+    {
+        return store.getPresenceIndexTable( attributeTypeOid ).exists( entryId );
+    }
+
+
+    @Override
+    public IndexCursor<String, ServerEntry> forwardCursor( String key ) throws Exception
+    {
+        // TODO Auto-generated method stub
+        return new HBasePresenceIndexCursor( key, store );
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseSubLevelIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseSubLevelIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseSubLevelIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseSubLevelIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,90 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseSubLevelIndexCursor;
+import org.apache.directory.server.core.partition.hbase.xdbmext.IndexFilteringExtension;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+
+
+/**
+ * HBase specific implementation of the sub-level index.
+ * There is no special one-level index table, but the tree table is used.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseSubLevelIndex extends AbstractHBaseIndex<Long, ServerEntry> implements
+    IndexFilteringExtension<Long, ServerEntry>
+{
+
+    private HBaseStore store;
+
+
+    public HBaseSubLevelIndex( HBaseStore store )
+    {
+        this.store = store;
+    }
+
+
+    public void close() throws Exception
+    {
+    }
+
+
+    public boolean forward( Long baseId, Long id ) throws Exception
+    {
+        // check if 'id' is (grand-)child of 'baseId'
+        // TODO: optimization: cache context entry ID 
+        long parentId = id;
+        while ( parentId != baseId && parentId != 0L )
+        {
+            //System.out.println("parent: " + parentId);
+            parentId = store.getMasterTable().fetchParentId( parentId );
+        }
+        //System.out.println("subLevelIndex.forward " + key + " -> " + id + " = " + (key==parentId));
+        return baseId == parentId;
+    }
+
+
+    @Override
+    public IndexCursor<Long, ServerEntry> forwardCursor( Long baseId ) throws Exception
+    {
+        return new HBaseSubLevelIndexCursor( baseId, store );
+    }
+
+
+    public IndexCursor<Long, ServerEntry> forwardFilteringCursor( Long baseId, ExprNode filter ) throws Exception
+    {
+        return new HBaseSubLevelIndexCursor( baseId, filter, store );
+    }
+
+
+    @Override
+    public int count( Long baseId ) throws Exception
+    {
+        return store.getMasterTable().getSubLevelCount( baseId );
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserColumnIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserColumnIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserColumnIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserColumnIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,66 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseUserColumnIndexCursor;
+import org.apache.directory.server.core.partition.hbase.table.HBaseColumnIndexTable;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+
+
+/**
+ * HBase specific implementation of an user index that reads
+ * candidates from treeInfo column family.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseUserColumnIndex extends HBaseUserIndex<HBaseColumnIndexTable>
+{
+
+    public HBaseUserColumnIndex( String attributeTypeOid, HBaseColumnIndexTable indexTable, HBaseStore store )
+    {
+        super( attributeTypeOid, indexTable, store );
+    }
+
+
+    @Override
+    public IndexCursor<Object, ServerEntry> forwardCursor( Object value ) throws Exception
+    {
+        return new HBaseUserColumnIndexCursor( attributeTypeOid, value, indexTable, store );
+    }
+
+
+    @Override
+    public IndexCursor<Object, ServerEntry> forwardCursor() throws Exception
+    {
+        return new HBaseUserColumnIndexCursor( attributeTypeOid, indexTable, store );
+    }
+
+
+    public IndexCursor<Object, ServerEntry> forwardSubstringCursor( SubstringNode node ) throws Exception
+    {
+        return new HBaseUserColumnIndexCursor( attributeTypeOid, node, indexTable, store );
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,198 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import java.util.regex.Pattern;
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseUserIndexReverseCursor;
+import org.apache.directory.server.core.partition.hbase.table.HBaseIndexTableBase;
+import org.apache.directory.server.core.partition.hbase.xdbmext.IndexSubstringExtension;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+
+
+/**
+ * Base implementation of an HBase specific user index.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class HBaseUserIndex<T extends HBaseIndexTableBase> extends AbstractHBaseIndex<Object, ServerEntry>
+    implements IndexSubstringExtension<Object, ServerEntry>
+{
+    protected T indexTable;
+    protected HBaseStore store;
+    protected String attributeTypeOid;
+
+
+    protected HBaseUserIndex( String attributeTypeOid, T indexTable, HBaseStore store )
+    {
+        this.attributeTypeOid = attributeTypeOid;
+        this.indexTable = indexTable;
+        this.store = store;
+    }
+
+
+    public void close() throws Exception
+    {
+    }
+
+
+    @Override
+    public int count() throws Exception
+    {
+        int count = store.getPresenceIndexTable( attributeTypeOid ).count();
+        return count;
+    }
+
+
+    @Override
+    public int count( Object value ) throws Exception
+    {
+        int count = indexTable.count( value );
+        return count;
+    }
+
+
+    @Override
+    public int greaterThanCount( Object value ) throws Exception
+    {
+        // TODO: scan?
+        // take a best guess
+        return count();
+    }
+
+
+    @Override
+    public int lessThanCount( Object value ) throws Exception
+    {
+        // TODO: scan?
+        // take a best guess
+        return count();
+    }
+
+
+    @Override
+    public boolean forward( Object value, Long id ) throws Exception
+    {
+        return indexTable.exists( value, id );
+    }
+
+
+    @Override
+    public IndexCursor<Object, ServerEntry> reverseCursor( Long id ) throws Exception
+    {
+        return new HBaseUserIndexReverseCursor( attributeTypeOid, id, store );
+    }
+
+
+    @Override
+    public boolean reverseLessOrEq( Long id, Object attrVal ) throws Exception
+    {
+        String testValue = ( String ) attrVal;
+        HBaseUserIndexReverseCursor cursor = new HBaseUserIndexReverseCursor( attributeTypeOid, id, store );
+        boolean match = false;
+
+        while ( cursor.next() )
+        {
+            String value = ( String ) cursor.get().getValue();
+            // TODO: use AT comparator!
+            if ( value.compareTo( testValue ) <= 0 )
+            {
+                match = true;
+                break;
+            }
+        }
+        cursor.close();
+
+        return match;
+    }
+
+
+    @Override
+    public boolean reverseGreaterOrEq( Long id, Object attrVal ) throws Exception
+    {
+        String testValue = ( String ) attrVal;
+        HBaseUserIndexReverseCursor cursor = new HBaseUserIndexReverseCursor( attributeTypeOid, id, store );
+        boolean match = false;
+
+        while ( cursor.next() )
+        {
+            String value = ( String ) cursor.get().getValue();
+            // TODO: use AT comparator!
+            if ( value.compareTo( testValue ) >= 0 )
+            {
+                match = true;
+                break;
+            }
+        }
+        cursor.close();
+
+        return match;
+    }
+
+
+    public int substringCount( SubstringNode node ) throws Exception
+    {
+        // TODO: only count 'counts':
+
+        // only count if expr contains an initial pattern and the total count of this index not too high.
+        // otherwise the scan may be really slow!
+        int totalCount = count();
+        if ( node.getInitial() != null && totalCount < 1000 )
+        {
+            //System.out.println("substringCount: scan for '" + node.getInitial() + "', totalCount=" + totalCount);
+
+            IndexCursor<Object, ServerEntry> cursor = forwardSubstringCursor( node );
+            int substringCount = 0;
+            //long t0 = System.currentTimeMillis();
+            while ( cursor.next() )
+            {
+                substringCount++;
+            }
+            //long t1 = System.currentTimeMillis();
+            //long t = t1 - t0;
+            //System.out.println( "  time=" + t );
+            //System.out.println( "  substringCount=" + substringCount );
+
+            return substringCount;
+        }
+        else
+        {
+            return totalCount;
+        }
+    }
+
+
+    public boolean forwardSubstring( SubstringNode expr, Pattern valuePattern ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public boolean forwardSubstring( SubstringNode expr, Pattern valuePattern, Long id ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserRowIndex.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserRowIndex.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserRowIndex.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/index/HBaseUserRowIndex.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,66 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.index;
+
+
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.hbase.HBaseStore;
+import org.apache.directory.server.core.partition.hbase.cursor.HBaseUserRowIndexCursor;
+import org.apache.directory.server.core.partition.hbase.table.HBaseRowIndexTable;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+
+
+/**
+ * HBase specific implementation of an user index that reads
+ * candidates from the row key.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class HBaseUserRowIndex extends HBaseUserIndex<HBaseRowIndexTable>
+{
+
+    public HBaseUserRowIndex( String attributeTypeOid, HBaseRowIndexTable indexTable, HBaseStore store )
+    {
+        super( attributeTypeOid, indexTable, store );
+    }
+
+
+    @Override
+    public IndexCursor<Object, ServerEntry> forwardCursor( Object value ) throws Exception
+    {
+        return new HBaseUserRowIndexCursor( attributeTypeOid, value, indexTable, store );
+    }
+
+
+    @Override
+    public IndexCursor<Object, ServerEntry> forwardCursor() throws Exception
+    {
+        return new HBaseUserRowIndexCursor( attributeTypeOid, indexTable, store );
+    }
+
+
+    public IndexCursor<Object, ServerEntry> forwardSubstringCursor( SubstringNode node ) throws Exception
+    {
+        return new HBaseUserRowIndexCursor( attributeTypeOid, node, indexTable, store );
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/mapreduce/IndexMapper.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/mapreduce/IndexMapper.java?rev=902620&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/mapreduce/IndexMapper.java (added)
+++ directory/sandbox/seelmann/hbase-partition/src/main/java/org/apache/directory/server/core/partition/hbase/mapreduce/IndexMapper.java Sun Jan 24 19:04:37 2010
@@ -0,0 +1,209 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.partition.hbase.mapreduce;
+
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.mapreduce.IndexTableReducer;
+import org.apache.hadoop.hbase.mapreduce.TableMapper;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+/**
+ * Creates indices from the master table.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class IndexMapper extends TableMapper<ImmutableBytesWritable, Result>
+{
+    private static final Log LOG = LogFactory.getLog( IndexTableReducer.class );
+
+    /** Counter enumeration to count added indices. */
+    private static enum Counters
+    {
+        INDEX, EXISTENCE
+    }
+
+    public static final String APACHEDS_TABLE_PREFIX = "apacheds.tablePrefix";
+    public static final String APACHEDS_INDEXED_ATTRIBUTES = "apacheds.indexedAttributes";
+
+    // master table columns
+    public static final byte[] TREE_INFO_FAMILY = Bytes.toBytes( "treeInfo" );
+    public static final byte[] ID_QUALIFIER = Bytes.toBytes( "id" );
+    public static final byte[] NORM_ATTRIBUTES_FAMILY = Bytes.toBytes( "normAttributes" );
+
+    // index table columns
+    public static final byte[] INFO_FAMILY = Bytes.toBytes( "info" );
+    //public static final byte[] ID_QUALIFIER = Bytes.toBytes( "id" );
+    public static final byte[] VALUE_QUALIFIER = Bytes.toBytes( "value" );
+    public static final byte[] COUNT_QUALIFIER = Bytes.toBytes( "count" );
+    public static final String DELIMITER_CHAR = ":";
+    public static final byte[] DELIMITER = Bytes.toBytes( DELIMITER_CHAR );
+
+    // HTable instances are cached
+    private HTable indexTable;
+    private HTable presenceIndexTable;
+
+
+    /**
+     * 
+     * @param row The current table row key.
+     * @param values The columns.
+     * @param context The current context.
+     * @throws IOException When something is broken with the data.
+     */
+    @Override
+    public void map( ImmutableBytesWritable row, Result values, Context context ) throws IOException
+    {
+        Set<String> indexedAttributes = new HashSet<String>( Arrays.asList( context.getConfiguration().getStrings(
+            APACHEDS_INDEXED_ATTRIBUTES ) ) );
+
+        // treeInfo:id
+        byte[] id = values.getValue( TREE_INFO_FAMILY, ID_QUALIFIER );
+        LOG.info( "create index for entry " + Bytes.toLong( id ) );
+
+        //System.out.println(values.getFamilyMap( arg0 ));
+        //new Exception().printStackTrace();
+        for ( KeyValue kv : values.list() )
+        {
+            if ( kv.matchingFamily( NORM_ATTRIBUTES_FAMILY ) )
+            {
+                // normAttributes:<attribute-OID>:<value>
+                byte[] qualifier = kv.getQualifier();
+                byte[] attrOid = Bytes.toBytes( Bytes.toString( qualifier ).split( DELIMITER_CHAR )[0] );
+                byte[] value = kv.getValue();
+                if ( indexedAttributes.contains( Bytes.toString( attrOid ) ) )
+                {
+                    add( qualifier, attrOid, value, id, context );
+                }
+            }
+        }
+    }
+
+
+    private void add( byte[] attrOidAndValue, byte[] attrOid, byte[] value, byte[] entryId, Context context )
+        throws IOException
+    {
+        LOG.info( "  index attribute " + Bytes.toString( attrOid ) + ":" + Bytes.toString( value ) );
+
+        String tablePrefix = context.getConfiguration().get( APACHEDS_TABLE_PREFIX );
+
+        // exact match (attribute=value): attribute:value:entryId -> entryId, value
+        // check first if the index already exists because we won't increment the index count
+        byte[] exactRow = Bytes.add( attrOidAndValue, DELIMITER, entryId );
+        Get exactGet = new Get( exactRow );
+        if ( !getIndexHTable( tablePrefix ).exists( exactGet ) )
+        {
+            Put exactPut = new Put( exactRow );
+            exactPut.setWriteToWAL( false );
+            exactPut.add( INFO_FAMILY, ID_QUALIFIER, entryId );
+            exactPut.add( INFO_FAMILY, VALUE_QUALIFIER, value );
+            getIndexHTable( tablePrefix ).put( exactPut );
+
+            // increment exact match count: attribute:value: -> count
+            byte[] exactCountRow = Bytes.add( attrOidAndValue, DELIMITER );
+            getIndexHTable( tablePrefix ).incrementColumnValue( exactCountRow, INFO_FAMILY, COUNT_QUALIFIER, 1L, false );
+
+            context.getCounter( Counters.INDEX ).increment( 1 );
+            LOG.info( "  added equals index " + Bytes.toString( attrOid ) + ":" + Bytes.toString( value ) + ":"
+                + Bytes.toLong( entryId ) );
+        }
+
+        // existence (attribute=*): attribute:entryId -> entryId
+        // check first if the index already exists because we won't increment the index count
+        byte[] existenceRow = Bytes.add( attrOid, DELIMITER, entryId );
+        Get existenceGet = new Get( existenceRow );
+        if ( !getPresenceIndexHTable( tablePrefix ).exists( existenceGet ) )
+        {
+            // get+put+put is not atomic!
+            Put existencePut = new Put( existenceRow );
+            existencePut.setWriteToWAL( false );
+            existencePut.add( INFO_FAMILY, ID_QUALIFIER, entryId );
+            getPresenceIndexHTable( tablePrefix ).put( existencePut );
+
+            // increment existence count: attribute: -> count
+            byte[] existenceCountRow = Bytes.add( attrOid, DELIMITER );
+            getPresenceIndexHTable( tablePrefix ).incrementColumnValue( existenceCountRow, INFO_FAMILY,
+                COUNT_QUALIFIER, 1L, false );
+
+            context.getCounter( Counters.EXISTENCE ).increment( 1 );
+            LOG.info( "  added existence index " + Bytes.toString( attrOid ) + ":" + Bytes.toLong( entryId ) );
+        }
+    }
+
+
+    private HTable getIndexHTable( String tablePrefix ) throws IOException
+    {
+        if ( indexTable == null )
+        {
+            HBaseConfiguration configuration = new HBaseConfiguration();
+            String tableName = tablePrefix + "index";
+
+            HBaseAdmin admin = new HBaseAdmin( configuration );
+            if ( !admin.tableExists( tableName ) )
+            {
+                HTableDescriptor descriptor = new HTableDescriptor( tableName );
+                descriptor.addFamily( new HColumnDescriptor( INFO_FAMILY ) );
+                admin.createTable( descriptor );
+            }
+
+            indexTable = new HTable( configuration, tableName );
+        }
+        return indexTable;
+    }
+
+
+    private HTable getPresenceIndexHTable( String tablePrefix ) throws IOException
+    {
+        if ( presenceIndexTable == null )
+        {
+            HBaseConfiguration configuration = new HBaseConfiguration();
+            String tableName = tablePrefix + "presence_index";
+
+            HBaseAdmin admin = new HBaseAdmin( configuration );
+            if ( !admin.tableExists( tableName ) )
+            {
+                HTableDescriptor descriptor = new HTableDescriptor( tableName );
+                descriptor.addFamily( new HColumnDescriptor( INFO_FAMILY ) );
+                admin.createTable( descriptor );
+            }
+
+            presenceIndexTable = new HTable( configuration, tableName );
+        }
+        return presenceIndexTable;
+    }
+}



Mime
View raw message