From 36050c5587e30c0e0b740166c73c2d145c3471d1 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Wed, 30 Apr 2008 23:38:25 +0000
Subject: [PATCH] Fix for issue where deleteing the last few entries indexed by a VLV index might cause a NPE.

---
 opends/src/server/org/opends/server/backends/jeb/VLVIndex.java                             |   12 +++
 opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java |   98 +++++++++++++++++++++++++++-----
 opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java                        |    8 ++
 opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java             |   21 +++++++
 4 files changed, 121 insertions(+), 18 deletions(-)

diff --git a/opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java b/opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java
index 94bf340..8fd9d1b 100644
--- a/opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java
+++ b/opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java
@@ -346,10 +346,16 @@
   /**
    * Encode this set to its database format.
    *
-   * @return The encoded bytes representing this set.
+   * @return The encoded bytes representing this set or null if
+   * this set is empty.
    */
   public byte[] toDatabase()
   {
+    if(size() == 0)
+    {
+      return null;
+    }
+
     byte[] entryIDBytes = JebFormat.entryIDListToDatabase(entryIDs);
     byte[] concatBytes = new byte[entryIDBytes.length + valuesBytes.length + 4];
     int v = entryIDs.length;
diff --git a/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java b/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java
index 928a0ca..81c16ea 100644
--- a/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java
+++ b/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java
@@ -878,8 +878,16 @@
                                         this);
       boolean success = sortValuesSet.remove(entryID, values);
       byte[] after = sortValuesSet.toDatabase();
-      data.setData(after);
-      put(txn, key, data);
+
+      if(after == null)
+      {
+        delete(txn, key);
+      }
+      else
+      {
+        data.setData(after);
+        put(txn, key, data);
+      }
 
       if(success)
       {
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
index 10ad394..1ef4ef4 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -72,6 +72,7 @@
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.DeleteOperation;
 import org.opends.server.extensions.ConfigFileHandler;
 import org.opends.server.loggers.TextAccessLogPublisher;
 import org.opends.server.loggers.TextErrorLogPublisher;
@@ -1071,6 +1072,26 @@
 
 
 
+  /**
+   * Deletess the provided entry from the Directory Server using an
+   * internal operation.
+   *
+   * @param  entry  The entry to be added.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  public static void deleteEntry(Entry entry)
+         throws Exception
+  {
+    InternalClientConnection conn =
+         InternalClientConnection.getRootConnection();
+
+    DeleteOperation deleteOperation = conn.processDelete(entry.getDN());
+    assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+  }
+
+
+
   public static boolean canBind(String dn, String pw) throws Exception
   {
     // Check that the user can bind.
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
index a9a9320..451e81a 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java
@@ -88,6 +88,8 @@
 
   TreeSet<SortValues> expectedSortedValues;
 
+  List<Entry> entries;
+
   @BeforeClass
   public void setUp() throws Exception {
     TestCaseUtils.startServer();
@@ -112,21 +114,8 @@
     suffixDN          = DN.decode("dc=vlvtest,dc=com");
 
     expectedSortedValues = new TreeSet<SortValues>();
-  }
 
-  @AfterClass
-  public void cleanUp() throws Exception {
-  }
-
-  /**
-   * Populates the JE DB with a set of test data.
-   *
-   * @throws  Exception  If an unexpected problem occurs.
-   */
-  private void populateDB()
-      throws Exception
-  {
-    List<Entry> entries = TestCaseUtils.makeEntries(
+    entries = TestCaseUtils.makeEntries(
         "dn: dc=vlvtest,dc=com",
         "objectClass: top",
         "objectClass: domain",
@@ -223,7 +212,20 @@
         "sn: Zorro",
         "cn: Zorro"
     );
+  }
 
+  @AfterClass
+  public void cleanUp() throws Exception {
+  }
+
+  /**
+   * Populates the JE DB with a set of test data.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  private void populateDB()
+      throws Exception
+  {
     long id = 1;
     for(Entry entry : entries)
     {
@@ -234,8 +236,74 @@
     }
   }
 
-
   @Test
+  public void testDel() throws Exception
+  {
+    populateDB();
+
+    TestCaseUtils.deleteEntry(entries.get(1));
+    TestCaseUtils.deleteEntry(entries.get(entries.size() - 1));
+
+    be=(BackendImpl) DirectoryServer.getBackend(beID);
+    RootContainer rootContainer = be.getRootContainer();
+    EntryContainer entryContainer =
+        rootContainer.getEntryContainer(DN.decode("dc=vlvtest,dc=com"));
+
+    for(VLVIndex vlvIndex : entryContainer.getVLVIndexes())
+    {
+      if(vlvIndex.getName().contains("testvlvindex"))
+      {
+
+
+        SortValuesSet svs1 =
+            vlvIndex.getSortValuesSet(null, 0,
+                                      expectedSortedValues.first().getValues());
+
+        assertNotNull(svs1);
+        assertEquals(svs1.size(), 3);
+
+        SortValuesSet svs2 =
+            vlvIndex.getSortValuesSet(null, 0,
+                                      expectedSortedValues.last().getValues());
+
+        assertNotNull(svs2);
+        assertEquals(svs2.size(), 5);
+      }
+    }
+
+    for(int i = 2; i <= entries.size() - 2; i++)
+    {
+      TestCaseUtils.deleteEntry(entries.get(i));
+    }
+    // Delete the base entry
+    TestCaseUtils.deleteEntry(entries.get(0));
+
+    for(VLVIndex vlvIndex : entryContainer.getVLVIndexes())
+    {
+      if(vlvIndex.getName().contains("testvlvindex"))
+      {
+
+
+        SortValuesSet svs1 =
+            vlvIndex.getSortValuesSet(null, 0,
+                                      expectedSortedValues.first().getValues());
+
+        assertNotNull(svs1);
+        assertEquals(svs1.size(), 0);
+        assertNull(svs1.getKeyBytes());
+
+        SortValuesSet svs2 =
+            vlvIndex.getSortValuesSet(null, 0,
+                                      expectedSortedValues.last().getValues());
+
+        assertNotNull(svs2);
+        assertEquals(svs1.size(), 0);
+        assertNull(svs1.getKeyBytes());
+      }
+    }
+  }
+
+  @Test( dependsOnMethods = { "testDel" } )
   public void testAdd() throws Exception
   {
     populateDB();

--
Gitblit v1.10.0