You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2010/03/19 17:59:01 UTC

svn commit: r925326 [2/4] - in /directory/sandbox/seelmann/hbase-partition-test: ./ src/ src/main/ src/test/ src/test/java/ src/test/java/org/ src/test/java/org/apache/ src/test/java/org/apache/directory/ src/test/java/org/apache/directory/server/ src/...

Added: directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionIT.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionIT.java?rev=925326&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionIT.java (added)
+++ directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionIT.java Fri Mar 19 16:59:00 2010
@@ -0,0 +1,1143 @@
+/*
+ *   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.it;
+
+
+import static org.apache.directory.server.integ.ServerIntegrationUtils.getWiredContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.core.partition.hbase.HBaseDistributedPartition;
+import org.apache.directory.server.core.partition.hbase.SingleColumnQualifierFilter;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserColumnIndex;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserRowIndex;
+import org.apache.directory.server.core.partition.hbase.table.HBaseMasterTable;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.Modification;
+import org.apache.directory.shared.ldap.entry.ModificationOperation;
+import org.apache.directory.shared.ldap.entry.client.ClientModification;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientAttribute;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.SearchScope;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.name.RDN;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HTable;
+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.BinaryComparator;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.FilterList.Operator;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(FrameworkRunner.class)
+@CreateDS(name = "hbase", enableChangeLog = false, partitions =
+    { @CreatePartition(name = "hbase", suffix = "o=hbase", type = HBaseDistributedPartition.class, indexes =
+        { @CreateIndex(attribute = "cn", cacheSize = 100, type = HBaseUserColumnIndex.class),
+            @CreateIndex(attribute = "uid", cacheSize = 100, type = HBaseUserColumnIndex.class),
+            @CreateIndex(attribute = "dc", cacheSize = 10, type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "o", cacheSize = 10, type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "ou", cacheSize = 100, type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "objectClass", cacheSize = 100, type = HBaseUserRowIndex.class) }) })
+@CreateLdapServer(transports =
+    { @CreateTransport(protocol = "LDAP") })
+public class HBasePartitionIT extends AbstractHBasePartitionIT
+{
+
+    @Before
+    public void initTestData() throws Exception
+    {
+        if ( !session.exists( new DN( "o=hbase" ) ) || !session.exists( new DN( "ou=test-ou,o=hbase" ) )
+            || !session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) )
+        {
+            createBasicTestData( ldapServer );
+        }
+        if ( !session.exists( new DN( "ou=test1000,o=hbase" ) ) )
+        {
+            createTestData( 1000, "000", ldapServer );
+        }
+    }
+
+
+    @Test
+    public void first() throws Exception
+    {
+    }
+
+
+    @Test
+    @Ignore
+    public void testScannerFilter() throws Exception
+    {
+        System.out.println("testScannerFiler");
+        HBaseConfiguration conf = adapter.getHBaseConfigurtion();
+        HTable table = new HTable( conf, "apacheds_hbase_tree" );
+
+        {
+            Scan scan = new Scan();
+            ResultScanner scanner = table.getScanner( scan );
+            Iterator<Result> iterator = scanner.iterator();
+            int count = 0;
+            while ( iterator.hasNext() )
+            {
+                iterator.next();
+                count++;
+            }
+            System.out.println( "Full scan before delete " + count );
+        }
+
+        {
+            Scan scan = new Scan();
+            scan.addFamily( HBaseMasterTable.TREE_INFO_FAMILY );
+            Filter filter = new SingleColumnValueFilter( HBaseMasterTable.TREE_INFO_FAMILY,
+                HBaseMasterTable.STATUS_QUALIFIER, CompareOp.EQUAL, HBaseMasterTable.EXISTS );
+            scan.setFilter( filter );
+            ResultScanner scanner = table.getScanner( scan );
+            Iterator<Result> iterator = scanner.iterator();
+            int count = 0;
+            while ( iterator.hasNext() )
+            {
+                iterator.next();
+                count++;
+            }
+            System.out.println( "Filtered scan before delete " + count );
+        }
+
+        session.delete( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        session.delete( new DN( "ou=test-ou,o=hbase" ) );
+
+        {
+            Scan scan = new Scan();
+            ResultScanner scanner = table.getScanner( scan );
+            Iterator<Result> iterator = scanner.iterator();
+            int count = 0;
+            while ( iterator.hasNext() )
+            {
+                iterator.next();
+                count++;
+            }
+            System.out.println( "Full scan after delete " + count );
+        }
+
+        {
+            Scan scan = new Scan();
+            scan.addFamily( HBaseMasterTable.TREE_INFO_FAMILY );
+            scan.addFamily( HBaseMasterTable.NORM_ATTRIBUTES_FAMILY );
+            
+            Filter mainFilter = new SingleColumnValueFilter( HBaseMasterTable.TREE_INFO_FAMILY,
+                HBaseMasterTable.STATUS_QUALIFIER, CompareOp.EQUAL, HBaseMasterTable.EXISTS );
+            Filter filter = null;
+            if ( mainFilter != null )
+            {
+                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 );
+                filter = filterList;
+            }
+            Filter existsFilter = new SingleColumnValueFilter( HBaseMasterTable.TREE_INFO_FAMILY,
+                HBaseMasterTable.STATUS_QUALIFIER, CompareOp.EQUAL, HBaseMasterTable.EXISTS );
+            if(filter != null)
+            {
+                FilterList filterList = new FilterList( Operator.MUST_PASS_ALL );
+                filterList.addFilter( filter );
+                filterList.addFilter( existsFilter );
+                filter = filterList;
+            }
+            else
+            {
+                filter = existsFilter;
+            }
+            System.out.println(filter);
+            scan.setFilter( filter );
+
+            
+            ResultScanner scanner = table.getScanner( scan );
+            Iterator<Result> iterator = scanner.iterator();
+            int count = 0;
+            while ( iterator.hasNext() )
+            {
+                iterator.next();
+                count++;
+            }
+            System.out.println( "Filtered scan after delete " + count );
+        }
+
+    }
+
+
+    @Test
+    public void testDelete() throws Exception
+    {
+        session.delete( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        session.delete( new DN( "ou=test-ou,o=hbase" ) );
+
+        assertFalse( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        assertFalse( session.exists( new DN( "ou=test-ou,o=hbase" ) ) );
+
+        // TODO: assert updates in HBase (id2dn, master, index, one-level-count, sub-level-counts)
+    }
+
+
+    @Test
+    public void testModify() throws Exception
+    {
+        // reset initial values
+        List<Modification> resetMods = new ArrayList<Modification>();
+        resetMods.add( new ClientModification( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultClientAttribute(
+            "telephoneNumber" ) ) );
+        resetMods.add( new ClientModification( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultClientAttribute(
+            "description", "description1", "description2" ) ) );
+        resetMods.add( new ClientModification( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultClientAttribute(
+            "seeAlso", "uid=admin,ou=system" ) ) );
+        resetMods.add( new ClientModification( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultClientAttribute(
+            "userPassword", "secret1" ) ) );
+        session.modify( new DN( "cn=test-person,ou=test-ou,o=hbase" ), resetMods );
+
+        // assert initial values
+        ClonedServerEntry entry = session.lookup( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertNull( entry.get( "telephoneNumber" ) );
+        assertNotNull( entry.get( "description" ) );
+        assertEquals( 2, entry.get( "description" ).size() );
+        assertNotNull( entry.get( "seeAlso" ) );
+        assertEquals( "uid=admin,ou=system", entry.get( "seeAlso" ).getString() );
+        assertNotNull( entry.get( "userPassword" ) );
+        assertEquals( "secret1", StringTools.utf8ToString( entry.get( "userPassword" ).getBytes() ) );
+
+        // apply modifications
+        List<Modification> modifications = new ArrayList<Modification>();
+        modifications.add( new ClientModification( ModificationOperation.ADD_ATTRIBUTE, new DefaultClientAttribute(
+            "telephoneNumber", "123", "456" ) ) );
+        modifications.add( new ClientModification( ModificationOperation.REMOVE_ATTRIBUTE, new DefaultClientAttribute(
+            "description", "description1" ) ) );
+        modifications.add( new ClientModification( ModificationOperation.REMOVE_ATTRIBUTE, new DefaultClientAttribute(
+            "seeAlso" ) ) );
+        modifications.add( new ClientModification( ModificationOperation.REPLACE_ATTRIBUTE, new DefaultClientAttribute(
+            "userPassword", "secret2" ) ) );
+        session.modify( new DN( "cn=test-person,ou=test-ou,o=hbase" ), modifications );
+
+        entry = session.lookup( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertNotNull( entry.get( "telephoneNumber" ) );
+        assertEquals( 2, entry.get( "telephoneNumber" ).size() );
+        assertNotNull( entry.get( "description" ) );
+        assertEquals( "description2", entry.get( "description" ).getString() );
+        assertNull( entry.get( "seeAlso" ) );
+        assertNotNull( entry.get( "userPassword" ) );
+        assertEquals( "secret2", StringTools.utf8ToString( entry.get( "userPassword" ).getBytes() ) );
+    }
+
+
+    @Test
+    public void testRenameLeaf() throws Exception
+    {
+        session.rename( new DN( "cn=test-person,ou=test-ou,o=hbase" ), new RDN( "cn=Test-Person2" ), false );
+        assertFalse( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=Test-Person2,ou=test-ou,o=hbase" ) ) );
+        ClonedServerEntry entry = session.lookup( new DN( "cn=Test-Person2,ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertNotNull( entry.get( "cn" ) );
+        assertEquals( 2, entry.get( "cn" ).size() );
+        assertTrue( entry.get( "cn" ).contains( "test-person" ) );
+        assertTrue( entry.get( "cn" ).contains( "Test-Person2" ) );
+
+        session.rename( new DN( "cn=test-person2,ou=test-ou,o=hbase" ), new RDN( "cn=test-person" ), true );
+        assertFalse( session.exists( new DN( "cn=Test-Person2,ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        entry = session.lookup( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertNotNull( entry.get( "cn" ) );
+        assertEquals( 1, entry.get( "cn" ).size() );
+        assertEquals( "test-person", entry.get( "cn" ).getString() );
+    }
+
+
+    @Test
+    public void testRenameBranch() throws Exception
+    {
+        session.rename( new DN( "ou=test-ou,o=hbase" ), new RDN( "OU=Test-Ou2" ), false );
+        assertFalse( session.exists( new DN( "ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "ou=test-ou2,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=test-person,ou=test-ou2,o=hbase" ) ) );
+        ClonedServerEntry entry = session.lookup( new DN( "ou=test-ou2,o=hbase" ) );
+        assertNotNull( entry );
+        assertNotNull( entry.get( "ou" ) );
+        assertEquals( 2, entry.get( "ou" ).size() );
+        assertTrue( entry.get( "ou" ).contains( "test-ou" ) );
+        assertTrue( entry.get( "ou" ).contains( "Test-Ou2" ) );
+
+        session.rename( new DN( "ou=test-ou2,o=hbase" ), new RDN( "ou=test-ou" ), true );
+        assertFalse( session.exists( new DN( "ou=test-ou2,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        entry = session.lookup( new DN( "ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertNotNull( entry.get( "ou" ) );
+        assertEquals( 1, entry.get( "ou" ).size() );
+        assertEquals( "test-ou", entry.get( "ou" ).getString() );
+    }
+
+
+    @Test
+    public void testMove() throws Exception
+    {
+        session.move( new DN( "cn=test-person,ou=test-ou,o=hbase" ), new DN( "o=hbase" ) );
+        assertFalse( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=test-person,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "ou=test-ou,o=hbase" ) ) );
+
+        session.move( new DN( "cn=test-person,o=hbase" ), new DN( "ou=test-ou,o=hbase" ) );
+        assertTrue( session.exists( new DN( "ou=test-ou,o=hbase" ) ) );
+        assertTrue( session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) );
+        assertFalse( session.exists( new DN( "cn=test-person,o=hbase" ) ) );
+    }
+
+
+    @Test
+    public void testLookup1() throws Exception
+    {
+        ClonedServerEntry entry = session.lookup( new DN( "o=hbase" ) );
+        assertNotNull( entry );
+        assertEquals( "2.5.4.10=hbase", entry.getDn().getNormName() );
+    }
+
+
+    @Test
+    public void testLookup2() throws Exception
+    {
+        ClonedServerEntry entry = session.lookup( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+        assertNotNull( entry );
+        assertEquals( "2.5.4.3=test-person,2.5.4.11=test-ou,2.5.4.10=hbase", entry.getDn().getNormName() );
+    }
+
+
+    @Test
+    public void testLookupNonExisting() throws Exception
+    {
+        assertFalse( session.exists( new DN( "cn=qwertz,ou=test-ou,o=hbase" ) ) );
+        try
+        {
+            session.lookup( new DN( "cn=qwertz,ou=test-ou,o=hbase" ) );
+            fail();
+        }
+        catch ( NameNotFoundException e )
+        {
+            // expected
+        }
+    }
+
+
+    @Test
+    public void testSearchBaseEqualsFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.OBJECT, FilterParser
+            .parse( "(objectClass=organizationalUnit)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-ou", entry.get( "ou" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchBaseNotEqualsFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.OBJECT, FilterParser
+            .parse( "(!(objectClass=organizationalUnit))" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchBasePresenceFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "cn=test-person,ou=test-ou,o=hbase" ),
+            SearchScope.OBJECT, FilterParser.parse( "(objectClass=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchBasePresenceFilter2() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "cn=test-person,ou=test-ou,o=hbase" ),
+            SearchScope.OBJECT, FilterParser.parse( "(sn=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchBaseSubstringFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "cn=test-person,ou=test-ou,o=hbase" ),
+            SearchScope.OBJECT, FilterParser.parse( "(objectClass=per*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelEqualFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou=test-OU)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-ou", entry.get( "ou" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelEqualFilter2() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.ONELEVEL,
+            FilterParser.parse( "(objectClass=person)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "cn" ).get( 0 ).getString() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelEqualFilter3() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.ONELEVEL,
+            FilterParser.parse( "(cn=test-person)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "cn" ).get( 0 ).getString() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelNotEqualFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(!(ou=test-ou))" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+        assertTrue( actualDns.size() > 0 );
+        assertTrue( actualDns.size() < 6 );
+        assertTrue( actualDns.contains( "ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchOneLevelPresenceFilterIndexed() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(objectClass=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+        assertTrue( actualDns.size() > 0 );
+        assertTrue( actualDns.size() < 6 );
+        assertTrue( actualDns.contains( "ou=test-ou,o=hbase" ) );
+        assertTrue( actualDns.contains( "ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchOneLevelPresenceFilterUnindexed() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.ONELEVEL,
+            FilterParser.parse( "(sn=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test-person,ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-person", entry.get( "cn" ).get( 0 ).getString() );
+        assertEquals( "test-person", entry.get( "sn" ).get( 0 ).getString() );
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelPresenceFilterIndexed2() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.ONELEVEL,
+            FilterParser.parse( "(objectClass=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+        assertEquals( 1000, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchOneLevelSubstringInitialFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou=test-*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-ou", entry.get( "ou" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelSubstringAnyFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou=*-*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-ou", entry.get( "ou" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelSubstringFinalFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou=*-ou)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+
+        cursor.beforeFirst();
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "ou=test-ou,o=hbase", entry.getDn().getName() );
+        assertEquals( "test-ou", entry.get( "ou" ).get( 0 ).getString() );
+
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchOneLevelGreaterEqualsFilter() throws Exception
+    {
+        // not a good example to use ou for ordering filter...
+
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou>=test-)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+        assertTrue( actualDns.size() > 0 );
+        assertTrue( actualDns.size() < 6 );
+        assertTrue( actualDns.contains( "ou=test-ou,o=hbase" ) );
+        assertTrue( actualDns.contains( "ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchOneLevelLessEqualsFilter() throws Exception
+    {
+        // not a good example to use ou for ordering filter...
+
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+            .parse( "(ou<=u)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+        assertTrue( actualDns.size() > 0 );
+        assertTrue( actualDns.size() < 6 );
+        assertTrue( actualDns.contains( "ou=test-ou,o=hbase" ) );
+        assertTrue( actualDns.contains( "ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelEqualFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+            .parse( "(cn=test999)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        assertTrue( cursor.next() );
+        ServerEntry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test999,ou=test1000,o=hbase", entry.getDn().getName() );
+        assertEquals( "test999", entry.get( "cn" ).get( 0 ).getString() );
+        assertEquals( "test999", entry.get( "sn" ).get( 0 ).getString() );
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchSubLevelEqualFilterUnindexed() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+            .parse( "(sn=test999)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        assertTrue( cursor.next() );
+        ServerEntry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test999,ou=test1000,o=hbase", entry.getDn().getName() );
+        assertEquals( "test999", entry.get( "cn" ).get( 0 ).getString() );
+        assertEquals( "test999", entry.get( "sn" ).get( 0 ).getString() );
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchSubLevelOrEqualFilter() throws Exception
+    {
+        // 
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.SUBTREE, FilterParser
+            .parse( "(|(ou=test-ou)(cn=test-person))" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        actualDns.add( entry.getDn().getName() );
+
+        assertTrue( cursor.next() );
+        entry = cursor.get();
+        assertNotNull( entry );
+        actualDns.add( entry.getDn().getName() );
+
+        assertFalse( cursor.next() );
+
+        assertTrue( actualDns.contains( "ou=test-ou,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test-person,ou=test-ou,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelAndEqualFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(&(cn=test777)(objectClass=person))" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        assertTrue( cursor.next() );
+        Entry entry = cursor.get();
+        assertNotNull( entry );
+        assertEquals( "cn=test777,ou=test1000,o=hbase", entry.getDn().getName() );
+    }
+
+
+    @Test
+    public void testSearchSubLevelAndEqualFilterNoResult() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test-ou,o=hbase" ), SearchScope.SUBTREE, FilterParser
+            .parse( "(&(cn=test777)(objectClass=person))" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+        assertFalse( cursor.next() );
+    }
+
+
+    @Test
+    public void testSearchPresenceFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn=*)" ), AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 1000, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelSubstringInitialFilter() throws Exception
+    {
+        // uses sub-level index
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn=test99*)" ), AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 10, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test990,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test991,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test992,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test993,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test994,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test995,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test996,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test997,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test998,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+
+        // uses cn index
+        cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser.parse( "(cn=test99*)" ),
+            AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertTrue( actualDns.size() >= 10 );
+        assertTrue( actualDns.contains( "cn=test990,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test991,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test992,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test993,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test994,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test995,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test996,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test997,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test998,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelSubstringAnyFilter() throws Exception
+    {
+        // uses sub-level index
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn=*st00*)" ), AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 10, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test001,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test002,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test003,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test004,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test005,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test006,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test007,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test008,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test009,ou=test1000,o=hbase" ) );
+
+        // uses cn index
+        cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser.parse( "(cn=*st00*)" ),
+            AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertTrue( actualDns.size() >= 10 );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test001,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test002,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test003,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test004,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test005,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test006,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test007,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test008,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test009,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelSubstringFinalFilter() throws Exception
+    {
+        // uses sub-level index
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn=*99)" ), AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 10, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test099,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test199,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test299,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test399,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test499,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test599,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test699,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test799,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test899,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+
+        // uses cn index
+        cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser.parse( "(cn=*99)" ),
+            AliasDerefMode.DEREF_ALWAYS, null, 0, 0 );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertTrue( actualDns.size() >= 10 );
+        assertTrue( actualDns.contains( "cn=test099,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test199,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test299,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test399,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test499,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test599,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test699,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test799,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test899,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelGreaterEqualsFilter() throws Exception
+    {
+        // not a good example to use cn for ordering filter...
+
+        // uses sub-level index
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn>=TeSt900)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 100, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test900,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+
+        // uses cn index
+        cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser.parse( "(cn>=TeSt900)" ),
+            AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 100, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test900,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test999,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelLessEqualsFilter() throws Exception
+    {
+        // not a good examle to use cn for ordering filter...
+
+        // uses sub-level index
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(cn<=test099)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 100, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test099,ou=test1000,o=hbase" ) );
+        assertFalse( actualDns.contains( "cn=test100,ou=test1000,o=hbase" ) );
+
+        // uses cn index
+        cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser.parse( "(cn<=test099)" ),
+            AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+        }
+
+        assertEquals( 101, actualDns.size() );
+        assertTrue( actualDns.contains( "cn=test-person,ou=test-ou,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test000,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test099,ou=test1000,o=hbase" ) );
+        assertFalse( actualDns.contains( "cn=test100,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelMixedOrderingFilter() throws Exception
+    {
+        EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.SUBTREE,
+            FilterParser.parse( "(&(cn>=test200)(!(cn=test200))(!(cn=test250))(!(cn=test300))(cn<=test300))" ),
+            AliasDerefMode.DEREF_ALWAYS, null );
+
+        assertNotNull( cursor );
+        cursor.beforeFirst();
+
+        List<String> actualDns = new ArrayList<String>();
+
+        while ( cursor.next() )
+        {
+            actualDns.add( cursor.get().getDn().getName() );
+            //System.out.println(cursor.get().getDn().getName());
+        }
+
+        assertEquals( 98, actualDns.size() );
+        assertFalse( actualDns.contains( "cn=test200,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test201,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test249,ou=test1000,o=hbase" ) );
+        assertFalse( actualDns.contains( "cn=test250,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test251,ou=test1000,o=hbase" ) );
+        assertTrue( actualDns.contains( "cn=test299,ou=test1000,o=hbase" ) );
+        assertFalse( actualDns.contains( "cn=test300,ou=test1000,o=hbase" ) );
+    }
+
+
+    @Test
+    public void testSearchSubLevelEqualFilterOverWire() throws Exception
+    {
+        LdapContext ctx = getWiredContext( ldapServer );
+
+        for ( int i = 0; i < 10; i++ )
+        {
+            SearchControls searchControls = new SearchControls();
+            searchControls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+            NamingEnumeration<SearchResult> results = ctx.search( "o=hbase", "(cn=test555)", searchControls );
+            assertTrue( results.hasMore() );
+            SearchResult next = results.next();
+            assertNotNull( next );
+            assertFalse( results.hasMore() );
+            results.close();
+        }
+    }
+
+
+    @Test
+    public void last() throws Exception
+    {
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionPerformanceIT.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionPerformanceIT.java?rev=925326&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionPerformanceIT.java (added)
+++ directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBasePartitionPerformanceIT.java Fri Mar 19 16:59:00 2010
@@ -0,0 +1,555 @@
+/*
+ *   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.it;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
+import org.apache.directory.server.core.entry.DefaultServerEntry;
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.core.partition.hbase.HBaseDistributedPartition;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserColumnIndex;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserRowIndex;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.SearchScope;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(FrameworkRunner.class)
+@CreateDS(
+    name = "hbase", 
+    enableChangeLog = false,
+    partitions =
+    { 
+        @CreatePartition(
+            name = "hbase", 
+            suffix = "o=hbase", 
+            type = HBaseDistributedPartition.class,
+            indexes = {
+                @CreateIndex( attribute="cn", cacheSize=100, type = HBaseUserColumnIndex.class ),
+                @CreateIndex( attribute="uid", cacheSize=100, type = HBaseUserColumnIndex.class ),
+                @CreateIndex( attribute="dc", cacheSize=10, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="o", cacheSize=10, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="ou", cacheSize=100, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="objectClass", cacheSize=100, type = HBaseUserRowIndex.class )
+            }
+        ) 
+    })
+@CreateLdapServer(transports =
+    { @CreateTransport(protocol = "LDAP") })
+public class HBasePartitionPerformanceIT extends AbstractHBasePartitionIT
+{
+
+    @Before
+    public void initTestData() throws Exception
+    {
+        if ( !session.exists( new DN( "o=hbase" ) ) || !session.exists( new DN( "ou=test-ou,o=hbase" ) )
+            || !session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) )
+        {
+            createBasicTestData( ldapServer );
+        }
+        if ( !session.exists( new DN( "ou=test1000,o=hbase" ) ) )
+        {
+            createTestData( 1000, "000", ldapServer );
+        }
+        if ( !session.exists( new DN( "ou=test10000,o=hbase" ) ) )
+        {
+            createTestData( 10000, "0000", ldapServer );
+
+            // Flush and compact the database, otherwise the tests
+            // would run very slow and an OOM exception could occur.
+            compactDatabase( adapter.getHBaseConfigurtion() );
+        }
+    }
+
+
+    @Test
+    public void first() throws Exception
+    {
+    }
+
+
+    @Test
+    public void testAddDeletePerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        SchemaManager schemaManager = ldapServer.getDirectoryService().getSchemaManager();
+
+        DN dn = new DN( "cn=test000,ou=test-ou,o=hbase" );
+        ServerEntry entry = new DefaultServerEntry( schemaManager, dn );
+        entry.add( "objectClass", "top", "person" );
+        entry.add( "cn", "test000" );
+        entry.add( "sn", "test000" );
+        session.add( entry );
+
+        session.delete( dn );
+
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testAddDeletePerformance: " + t );
+    }
+
+
+    @Test
+    public void testAddPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        SchemaManager schemaManager = ldapServer.getDirectoryService().getSchemaManager();
+
+        DecimalFormat df = new DecimalFormat( "000" );
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String s = df.format( i );
+            ServerEntry entry = new DefaultServerEntry( schemaManager, new DN( "cn=test" + s
+                + ",ou=test-ou,o=hbase" ) );
+            entry.add( "objectClass", "top", "person" );
+            entry.add( "cn", "test" + s );
+            entry.add( "Sn", "test" + s );
+            session.add( entry );
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testAddPerformance: " + t );
+    }
+
+
+    @Test
+    public void testDeletePerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        DecimalFormat df = new DecimalFormat( "000" );
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String s = df.format( i );
+            session.delete( new DN( "cn=test" + s + ",ou=test-ou,o=hbase" ) );
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testDeletePerformance: " + t );
+    }
+
+
+    @Test
+    public void testLookupPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            ClonedServerEntry entry = session.lookup( new DN( "cn=test-person,ou=test-ou,o=hbase" ) );
+            assertNotNull( entry );
+            assertEquals( "2.5.4.3=test-person,2.5.4.11=test-ou,2.5.4.10=hbase", entry.getDn().getNormName() );
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testLookupPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomLookupPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            ClonedServerEntry entry = session.lookup( new DN( "cn=test" + cn + ",ou=test10000,o=hbase" ) );
+            assertNotNull( entry );
+            assertEquals( "2.5.4.3=test" + cn + ",2.5.4.11=test10000,2.5.4.10=hbase", entry.getDn().getNormName() );
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomLookupPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchOneLevelEqualFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+                .parse( "(objectClass=organizationalUnit)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse(cursor.next());
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchOneLevelEqualFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchOneLevelEqualFilterManyResultsPerformance() throws Exception
+    {
+        // TODO: slow
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1; i++ )
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "ou=test1000,o=hbase" ), SearchScope.ONELEVEL,
+                FilterParser.parse( "(objectClass=person)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+
+            List<String> actualDns = new ArrayList<String>();
+            while ( cursor.next() )
+            {
+                actualDns.add( cursor.get().getDn().getName() );
+            }
+            assertEquals( 1000, actualDns.size() );
+
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchOneLevelEqualFilterManyResultsPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchOneLevelEqualFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            String filter = "(cn=test" + cn + ")";
+            EntryFilteringCursor cursor = session.search( new DN( "ou=test10000,o=hbase" ), SearchScope.ONELEVEL,
+                FilterParser.parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchOneLevelEqualFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchOneLevelEqualFilterUnindexedPerformance() throws Exception
+    {
+        // TODO: slow
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ )
+        {
+            String sn = RandomStringUtils.randomNumeric( 4 );
+            String filter = "(sn=test" + sn + ")";
+            EntryFilteringCursor cursor = session.search( new DN( "ou=test10000,o=hbase" ), SearchScope.ONELEVEL,
+                FilterParser.parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchOneLevelEqualFilterUnindexedPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchOneLevelPresenceFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ ) // TODO
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+                .parse( "(objectClass=*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+
+            List<String> actualDns = new ArrayList<String>();
+            while ( cursor.next() )
+            {
+                actualDns.add( cursor.get().getDn().getName() );
+            }
+            assertTrue( actualDns.size() > 2 );
+            assertTrue( actualDns.size() < 6 );
+
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchOneLevelPresenceFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchOneLevelSubstringInitialFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ ) // TODO
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+                .parse( "(objectClass=org*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse(cursor.next());
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchOneLevelSubstringInitialFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchOneLevelSubstringAnyFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ ) // TODO
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.ONELEVEL, FilterParser
+                .parse( "(objectClass=*org*)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse(cursor.next());
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchOneLevelSubstringAnyFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSearchSubLevelEqualFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( "(objectClass=organizationalUnit)" ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse(cursor.next());
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testSearchSubLevelEqualFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testSequentialSearchSubLevelEqualFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        DecimalFormat df = new DecimalFormat( "000" );
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String cn = df.format( i );
+            String filter = "(cn=test" + cn + ")";
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertEquals( "test" + cn, cursor.get().get( "cn" ).getString() );
+            assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelEqualFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchSubLevelEqualFilterPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 1000; i++ )
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            String filter = "(cn=test" + cn + ")";
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelEqualFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchSubLevelSubstringInitialFilterUsingUserIndexPerformance() throws Exception
+    {
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ ) // TODO
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            String filter = "(cn=test" + cn + "*)";
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelSubstringInitialFilterUsingUserIndexPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchSubLevelSubstringInitialFilterUsingSubscopeIndexPerformance() throws Exception
+    {
+        // subtree scan: sub count of ou=test10000,o=hbase < cn index count
+        // TODO: doesn't scale!!!
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 10; i++ ) // TODO
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            //String cn = "9999";
+            String filter = "(cn=test" + cn + "*)";
+            EntryFilteringCursor cursor = session.search( new DN( "ou=test10000,o=hbase" ), SearchScope.SUBTREE,
+                FilterParser.parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelSubstringInitialFilterUsingSubscopeIndexPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchSubLevelSubstringInitialAnyFilterPerformance() throws Exception
+    {
+        // uses index: sub count of suffix > cn index count
+        // TODO: doesn't scale!!!
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 100; i++ )
+        {
+            String cn = RandomStringUtils.randomNumeric( 4 );
+            String filter = "(cn=test*" + cn + "*)";
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelSubstringInitialAnyFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void testRandomSearchSubLevelSubstringAnyFilterPerformance() throws Exception
+    {
+        // uses index: sub count of suffix > cn index count 
+        // TODO: doesn't scale!!!
+        long t0 = System.currentTimeMillis();
+        for ( int i = 0; i < 100; i++ )
+        {
+            //String cn = RandomStringUtils.randomNumeric( 4 );
+            String cn = "9999";
+            String filter = "(cn=*" + cn + "*)";
+            EntryFilteringCursor cursor = session.search( new DN( "o=hbase" ), SearchScope.SUBTREE, FilterParser
+                .parse( filter ), AliasDerefMode.DEREF_ALWAYS, null );
+
+            cursor.beforeFirst();
+            assertTrue( cursor.next() );
+            assertNotNull( cursor.get() );
+            //assertFalse( cursor.next() );
+            cursor.close();
+        }
+        long t1 = System.currentTimeMillis();
+        long t = t1 - t0;
+        System.out.println( "testRandomSearchSubLevelSubstringAnyFilterPerformance: " + t );
+    }
+
+
+    @Test
+    public void last() throws Exception
+    {
+    }
+
+}

Added: directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBaseRunner.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBaseRunner.java?rev=925326&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBaseRunner.java (added)
+++ directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/HBaseRunner.java Fri Mar 19 16:59:00 2010
@@ -0,0 +1,99 @@
+/*
+ *   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.it;
+
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.core.partition.hbase.HBaseDistributedPartition;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserColumnIndex;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserRowIndex;
+import org.apache.directory.shared.ldap.name.DN;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Starts up an ApacheDS LDAP server with an HBase partition.
+ * Also starts up up an embedded HDFS and HBase Mini Cluster and
+ * adds some test data. Note that the data is transient!
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@RunWith(FrameworkRunner.class)
+@CreateDS(
+    name = "hbase", 
+    enableChangeLog = false,
+    partitions =
+    { 
+        @CreatePartition(
+            name = "hbase", 
+            suffix = "o=hbase", 
+            type = HBaseDistributedPartition.class,
+            indexes = {
+                @CreateIndex( attribute="cn", cacheSize=100, type = HBaseUserColumnIndex.class ),
+                @CreateIndex( attribute="uid", cacheSize=100, type = HBaseUserColumnIndex.class ),
+                @CreateIndex( attribute="dc", cacheSize=10, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="o", cacheSize=10, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="ou", cacheSize=100, type = HBaseUserRowIndex.class ),
+                @CreateIndex( attribute="objectClass", cacheSize=100, type = HBaseUserRowIndex.class )
+            }
+        ) 
+    })
+@CreateLdapServer(transports =
+    { @CreateTransport(protocol = "LDAP") })
+@Ignore
+public class HBaseRunner extends AbstractHBasePartitionIT
+{
+
+    @Before
+    public void initTestData() throws Exception
+    {
+        if ( !session.exists( new DN( "o=hbase" ) ) || !session.exists( new DN( "ou=test-ou,o=hbase" ) )
+            || !session.exists( new DN( "cn=test-person,ou=test-ou,o=hbase" ) ) )
+        {
+            createBasicTestData( ldapServer );
+        }
+        if ( !session.exists( new DN( "ou=test1000,o=hbase" ) ) )
+        {
+            createTestData( 1000, "000", ldapServer );
+        }
+        if ( !session.exists( new DN( "ou=test10000,o=hbase" ) ) )
+        {
+            createTestData( 10000, "0000", ldapServer );
+        }
+        compactDatabase( adapter.getHBaseConfigurtion() );
+    }
+
+
+    @Test
+    public void runServer() throws Exception
+    {
+        System.out.println( "ApacheDS started on port " + ldapServer.getPort() + ", press any key to shutdown..." );
+        System.in.read();
+    }
+}

Added: directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/GetPerformanceEvaluation.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/GetPerformanceEvaluation.java?rev=925326&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/GetPerformanceEvaluation.java (added)
+++ directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/GetPerformanceEvaluation.java Fri Mar 19 16:59:00 2010
@@ -0,0 +1,86 @@
+/*
+ *   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.it.mapreduce;
+
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.util.Bytes;
+
+
+public class GetPerformanceEvaluation extends Thread
+{
+
+    static HBaseConfiguration CONF = new HBaseConfiguration();
+    static int THREADS = 10;
+    static int COUNT = 1000;
+    
+    public static void main( String[] args ) throws Exception
+    {
+        for ( int i = 0; i < THREADS; i++ )
+        {
+            new GetPerformanceEvaluation().start();
+        }
+    }
+
+
+    public void run()
+    {
+        try
+        {
+            HTable table = new HTable( CONF, "apacheds_example_master" );
+            // warm up
+            get( table );
+            get( table );
+            get( table );
+
+            long t1 = System.currentTimeMillis();
+            for ( int i = 0; i < COUNT; i++ )
+            {
+                get( table );
+            }
+            long t2 = System.currentTimeMillis();
+            long t = t2 - t1;
+            int rate = COUNT * 1000 / ( int ) t;
+            System.out.println( "--> " + t + " ms, " + rate + "/s" );
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    private void get( HTable table ) throws Exception
+    {
+        long l = ( long ) RandomUtils.nextInt( 1000000 );
+        //long l = 771664L + RandomUtils.nextInt( 1000 );
+        Get get = new Get( Bytes.toBytes( l ) ); // 25/s
+        //get.addColumn( Bytes.toBytes( "treeInfo" ), Bytes.toBytes( "upRdn" ) ); // 100/s
+        //byte[] oc0 = Bytes.add( Bytes.toBytes( "objectclass" ), Bytes.toBytes( 0 ) );
+        //get.addColumn( Bytes.toBytes( "upAttributes" ), oc0 ); // 50/s
+        Result result = table.get( get );
+        //System.out.println(result.getBytes().getSize());
+    }
+
+}
\ No newline at end of file

Added: directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/LdifImportAndIndexIT.java
URL: http://svn.apache.org/viewvc/directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/LdifImportAndIndexIT.java?rev=925326&view=auto
==============================================================================
--- directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/LdifImportAndIndexIT.java (added)
+++ directory/sandbox/seelmann/hbase-partition-test/src/test/java/org/apache/directory/server/core/partition/hbase/it/mapreduce/LdifImportAndIndexIT.java Fri Mar 19 16:59:00 2010
@@ -0,0 +1,188 @@
+/*
+ *   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.it.mapreduce;
+
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.core.partition.hbase.HBaseDistributedPartition;
+import org.apache.directory.server.core.partition.hbase.Utils;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserColumnIndex;
+import org.apache.directory.server.core.partition.hbase.index.HBaseUserRowIndex;
+import org.apache.directory.server.core.partition.hbase.it.AbstractHBasePartitionIT;
+import org.apache.directory.server.core.partition.hbase.mapreduce.IndexBuilder;
+import org.apache.directory.server.core.partition.hbase.mapreduce.LdifImporter;
+import org.apache.directory.server.core.partition.hbase.mapreduce.LdifInputFormat;
+import org.apache.directory.server.core.partition.hbase.mapreduce.TreeTableBuilder;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTable;
+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.mapreduce.TableMapReduceUtil;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.mapreduce.Job;
+import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
+import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+@RunWith(FrameworkRunner.class)
+@CreateDS(name = "example", enableChangeLog = false, partitions =
+    { @CreatePartition(name = "example", suffix = "dc=example,dc=com", type = HBaseDistributedPartition.class, indexes =
+        { @CreateIndex(attribute = "cn", type = HBaseUserColumnIndex.class),
+            @CreateIndex(attribute = "uid", type = HBaseUserColumnIndex.class),
+            @CreateIndex(attribute = "dc", type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "o", type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "ou", type = HBaseUserRowIndex.class),
+            @CreateIndex(attribute = "objectClass", type = HBaseUserRowIndex.class) }) })
+@CreateLdapServer(transports =
+    { @CreateTransport(protocol = "LDAP", port = 10389, nbThreads = 16) })
+public class LdifImportAndIndexIT extends AbstractHBasePartitionIT
+{
+
+    @Test
+    public void testLdifImport() throws Exception
+    {
+        // import master data
+        for ( int i = 2; i < 5; i++ )
+        {
+            long t0 = System.currentTimeMillis();
+            Configuration conf = new Configuration();
+            conf.set( LdifImporter.NAME_COMPONENT_COUNT, "" + i );
+            conf.set( LdifImporter.SUFFIX, "dc=example,dc=com" );
+            conf.set( LdifImporter.TABLE_PREFIX, "apacheds_example_" );
+
+            Job job = new Job( conf, "Import LDIF" );
+            job.setJarByClass( LdifImporter.class );
+
+            FileInputFormat.addInputPath(job, new Path("src/test/resources/testdata-5.ldif"));
+            //FileInputFormat.addInputPath( job, new Path( "src/test/resources/testdata-10000.ldif" ) );
+            job.setInputFormatClass( LdifInputFormat.class );
+            job.setMapperClass( LdifImporter.class );
+
+            TableMapReduceUtil.initTableReducerJob( ".META.", null, job );
+            job.setNumReduceTasks( 0 );
+
+            boolean status = job.waitForCompletion( true );
+            long t1 = System.currentTimeMillis();
+            long t = t1 - t0;
+            System.out.println( "Import LDIF " + status + " in " + t + "ms." );
+            //System.out.println( job.getCounters() );
+            System.out.println();
+        }
+        
+        // build tree table
+        {
+            long t0 = System.currentTimeMillis();
+            Configuration conf = new Configuration();
+            //conf.set( LdifImporter.NAME_COMPONENT_COUNT, ""+i );
+            conf.set( TreeTableBuilder.SUFFIX, "dc=example,dc=com" );
+            conf.set( TreeTableBuilder.TABLE_PREFIX, "apacheds_example_" );
+    
+            Job job = new Job( conf, "Build Tree Table" );
+            job.setJarByClass( TreeTableBuilder.class );
+    
+            TableMapReduceUtil.initTableMapperJob( "apacheds_example_master", new Scan(),
+                TreeTableBuilder.class, null, null, job );
+            job.setOutputFormatClass( NullOutputFormat.class );
+            job.setNumReduceTasks( 0 );
+    
+            boolean status = job.waitForCompletion( true );
+            long t1 = System.currentTimeMillis();
+            long t = t1 - t0;
+            System.out.println( "Build Tree Table " + status + " in " + t + "ms." );
+            //System.out.println( job.getCounters() );
+            System.out.println();
+        }
+
+        // build indices
+        {
+            long t0 = System.currentTimeMillis();
+            Configuration conf = new Configuration();
+            //conf.set( LdifImporter.NAME_COMPONENT_COUNT, ""+i );
+            conf.set( IndexBuilder.SUFFIX, "dc=example,dc=com" );
+            conf.set( IndexBuilder.TABLE_PREFIX, "apacheds_example_" );
+            conf.set( IndexBuilder.COLUMN_INDICES, "cn,uid" );
+            conf.set( IndexBuilder.ROW_INDICES, "dc,o,ou,objectClass" );
+    
+            Job job = new Job( conf, "Build Index" );
+            job.setJarByClass( IndexBuilder.class );
+    
+            TableMapReduceUtil.initTableMapperJob( "apacheds_example_master", new Scan(),
+                IndexBuilder.class, null, null, job );
+            job.setOutputFormatClass( NullOutputFormat.class );
+            job.setNumReduceTasks( 0 );
+    
+            boolean status = job.waitForCompletion( true );
+            long t1 = System.currentTimeMillis();
+            long t = t1 - t0;
+            System.out.println( "Build Index " + status + " in " + t + "ms." );
+            //System.out.println( job.getCounters() );
+            System.out.println();
+        }
+
+        //
+        //        ClonedServerEntry entry = ldapServer.getDirectoryService().getAdminSession().lookup(
+        //            new DN( "dc=example,dc=com" ) );
+        //        assertNotNull( entry );
+        //
+        dump();
+        System.out.println( "ApacheDS started on port " + ldapServer.getPort() + ", press any key to shutdown..." );
+        System.in.read();
+    }
+
+
+    private void dump() throws Exception
+    {
+        HTable masterHTable = new HTable( "apacheds_example_master" );
+        Get masterGet = new Get( Bytes.toBytes( 0L ) );
+        System.out.println( masterHTable.exists( masterGet ) );
+        masterGet = new Get( Bytes.toBytes( 1L ) );
+        System.out.println( masterHTable.exists( masterGet ) );
+        ResultScanner masterScanner = masterHTable.getScanner( new Scan() );
+        Result masterResult;
+        while ( ( masterResult = masterScanner.next() ) != null )
+        {
+            System.out.println( "master: " + Utils.getPrintableString( masterResult.getRow() ) );
+        }
+
+        HTable treeHTable = new HTable( "apacheds_example_tree" );
+        ResultScanner treeScanner = treeHTable.getScanner( new Scan() );
+        Result treeResult;
+        while ( ( treeResult = treeScanner.next() ) != null )
+        {
+            System.out.println( "tree: " + Utils.getPrintableString( treeResult.getRow() ) );
+        }
+    }
+
+}
\ No newline at end of file