mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

boli
01.38.2008 36050c5587e30c0e0b740166c73c2d145c3471d1
Fix for issue where deleteing the last few entries indexed by a VLV index might cause a NPE.

Fix for issue 3208
4 files modified
135 ■■■■ changed files
opends/src/server/org/opends/server/backends/jeb/SortValuesSet.java 8 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/VLVIndex.java 8 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java 21 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVLVIndex.java 98 ●●●● patch | view | raw | blame | history
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;
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();
      if(after == null)
      {
        delete(txn, key);
      }
      else
      {
      data.setData(after);
      put(txn, key, data);
      }
      if(success)
      {
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.
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();