Uploaded image for project: 'Directory ApacheDS'
  1. Directory ApacheDS
  2. DIRSERVER-1369

Concurrent bind and unbind of objects puts ADS in an inconsistent (unusable) state.

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Blocker
    • Resolution: Fixed
    • 1.5.4
    • 1.5.5
    • None
    • None
    • Windows-xp, JDK-1.5

    Description

      This is with reference to a problem we faced when performing concurrent bind and unbind of objects with ADS-1.5.4 release build.
      Please find the java program at the bottom.

      Steps to reproduce:
      1. Install apache_1.5.4 zip version of it and not the installer and change port numbers to 1389 and 1636 respectively.
      2. Create a naming context ( JDBM partition) on the lines of dc=example,dc=com
      3. Also create the entry dc=example,dc=com
      4. Run the java program provided below.

      Actual Result:
      The console throws up numerous Naming Exceptions with message "[LDAP: error code 80 - OTHER: failed for Del request
      Entry : '2.5.4.3=adsadminpref_thread-11,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com'
      : null]; remaining name 'cn=tdsadminPref_Thread-11,dc=telelogic,dc=com' " for each thread operating on a preference object.

      As a result, the server gets into an inconsistent state and unoperational.

      Expected Result:
      The server should continuously bind and unbind the java hash table object.

      What could have caused this and how do we correct this.
      Are there any specific configurations to be made in the server.xml.
      I tried modifying some of the attributes like syncOnWrite, syncOnMillis, maxThreads, cachesize and also rebind (instead of bind and unbind) in the java program , but in vain.
      This is very important for us and do help us in this regard.

      Java program:

      import java.util.Date;
      import java.util.HashMap;
      import java.util.Hashtable;
      import java.util.Map;

      import javax.naming.CommunicationException;
      import javax.naming.Context;
      import javax.naming.NameAlreadyBoundException;
      import javax.naming.NameNotFoundException;
      import javax.naming.NamingException;
      import javax.naming.ldap.InitialLdapContext;
      import javax.naming.ldap.LdapContext;

      import com.telelogic.tds.common.TDSConstants;
      import com.telelogic.tds.common.TDSProperties;
      import com.telelogic.tds.engine.ldap.jndi.TDSDirObjectConstants;

      public class MultiThreadedTest extends Thread {

      @Override
      public void run() {

      try {

      LdapContext _tdsContext = null, _cntx;
      _tdsContext = getContext();

      // Create the initial context
      Map<String, Object> hMap = new HashMap<String, Object>();
      hMap.put("data", "dsfdfd");

      // authenticate user
      int delay = 1;
      while (true) {

      try

      { System.out.println(" Ops started " + getName()); _cntx = _tdsContext.newInstance(null); setUserPreferences(_cntx, "adsadminPref_" + getName(), hMap); System.out.println(new Date() + " Preferences SET " + getName() + " " + getId() + " SIZE-- " + ((hMap.get("data") != null) ? hMap.get("data") .toString().length() : 0)); _cntx.close(); System.out.println(" Ops conducted successfully " + getName()); }

      catch (NamingException e)

      { System.out.println(new Date() + " NAMING EXCETPION" + getName() + " " + getId()); e.printStackTrace(); }

      catch (Exception ex)

      { System.out.println(new Date() + " NAMING EXCETPION" + getName() + " " + getId()); ex.printStackTrace(); }

      Thread.sleep(delay);
      }
      } catch (Throwable e)

      { e.printStackTrace(); }

      }

      private static LdapContext getContext() {
      Hashtable<String, String> env = new Hashtable<String, String>();
      LdapContext context = null;
      String adminName = "uid=admin,ou=system";
      String adminPassword = "secret";

      env.put(Context.INITIAL_CONTEXT_FACTORY,
      "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      env.put(Context.SECURITY_PRINCIPAL, adminName);
      env.put(Context.SECURITY_CREDENTIALS, adminPassword);
      //env.put(Context.PROVIDER_URL, "ldap://10.255.0.40:389");
      env.put(Context.PROVIDER_URL, "ldap://localhost:1389");
      env.put(TDSConstants.JNDI_LDAP_CONNECTION_TIMEOUT, TDSProperties
      .getProperty(TDSConstants.LDAP_CONNECTION_TIMEOUT, "2000"));

      env.put("com.sun.jndi.ldap.connect.pool", TDSProperties.getProperty(
      "com.sun.jndi.ldap.connect.pool", "true"));

      try

      { context = new InitialLdapContext(env, null); }

      catch (NamingException ne)

      { System.exit(1); }

      return context;
      }

      public static void setUserPreferences(LdapContext context, String userName,
      Map<String, Object> attributes) throws NamingException {

      LdapContext derivedContext = context;

      String bindOp =
      TDSDirObjectConstants.CN + TDSDirObjectConstants.EQUAL_SYNTAX
      + userName + "," + "dc=example,dc=com";

      try {

      try

      { // Step 1: Unbind the user preferences data derivedContext.unbind(bindOp); }

      catch (CommunicationException ce)

      { System.out.println("Trying to re-connect to RDS"); //Impl reconnect logic }

      catch (NameNotFoundException nnf)

      { System.out.println("User: " + userName + " cannot be found in the Ldap server"); }

      try

      { // Step 2: Bind the user preferences data derivedContext.bind(bindOp, attributes); }

      catch (CommunicationException ce)

      { System.out.println("Trying to re-connect to RDS"); }

      catch (NameAlreadyBoundException nab)

      { System.out.println("User: " + userName + " already exists in the Ldap server"); }

      //derivedContext.rebind(bindOp, attributes);
      } catch (NamingException ne)

      { System.out.println("Could not set user profile for user: " + userName); throw ne; }

      }

      /**

      • @param args
        */
        public static void main(String[] args)
        Unknown macro: { Thread t1, t2 = null; for (int i = 0; i < 15; ++i) { t1 = new MultiThreadedTest(); t1.start(); } }

      }

      Attachments

        1. MultiThreadedTest.java
          7 kB
          Sumit Goyal
        2. MultiThreadedTest.java
          5 kB
          Emmanuel Lécharny
        3. MultiThreadedTest.java
          5 kB
          Murali Krishna

        Issue Links

          There are no Sub-Tasks for this issue.

          Activity

            People

              Unassigned Unassigned
              murakris_gk Murali Krishna
              Votes:
              3 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - 120h
                  120h
                  Remaining:
                  Remaining Estimate - 120h
                  120h
                  Logged:
                  Time Spent - Not Specified
                  Not Specified