private File createCleanDir() throws IOException {
   String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
   String path =
       System.getProperty(TestCaseUtils.PROPERTY_BUILD_DIR, buildRoot + File.separator + "build");
   path = path + File.separator + "unit-tests" + File.separator + "JEReplicaDB";
   final File testRoot = new File(path);
   TestCaseUtils.deleteDirectory(testRoot);
   testRoot.mkdirs();
   return testRoot;
 }
Example #2
0
  /**
   * The main method for ExportLDIF tool.
   *
   * @param args The command-line arguments provided to this program.
   */
  public static void main(String[] args) {
    int retCode = mainExportLDIF(args, true, System.out, System.err);

    if (retCode != 0) {
      System.exit(filterExitCode(retCode));
    }
  }
    @Override
    public void run() {
      long latestCount = reader.getEntriesRead() + 0;
      long deltaCount = latestCount - previousCount;
      long latestTime = System.currentTimeMillis();
      long deltaTime = latestTime - previousTime;
      if (deltaTime == 0) {
        return;
      }
      long entriesRead = reader.getEntriesRead();
      long entriesIgnored = reader.getEntriesIgnored();
      long entriesRejected = reader.getEntriesRejected();
      float rate = 1000f * deltaCount / deltaTime;
      logger.info(NOTE_IMPORT_PROGRESS_REPORT, entriesRead, entriesIgnored, entriesRejected, rate);

      previousCount = latestCount;
      previousTime = latestTime;
    }
  /** {@inheritDoc} */
  @Override()
  public LDIFImportResult importLDIF(LDIFImportConfig importConfig) throws DirectoryException {
    RuntimeInformation.logInfo();

    // If the backend already has the root container open, we must use the same
    // underlying root container
    boolean openRootContainer = rootContainer == null;

    // If the rootContainer is open, the backend is initialized by something
    // else.
    // We can't do import while the backend is online.
    if (!openRootContainer) {
      Message message = ERR_JEB_IMPORT_BACKEND_ONLINE.get();
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message);
    }

    try {
      EnvironmentConfig envConfig = new EnvironmentConfig();

      envConfig.setAllowCreate(true);
      envConfig.setTransactional(false);
      envConfig.setDurability(Durability.COMMIT_NO_SYNC);
      envConfig.setLockTimeout(0, TimeUnit.SECONDS);
      envConfig.setTxnTimeout(0, TimeUnit.SECONDS);
      envConfig.setConfigParam(
          EnvironmentConfig.CLEANER_MIN_FILE_UTILIZATION,
          String.valueOf(cfg.getDBCleanerMinUtilization()));
      envConfig.setConfigParam(
          EnvironmentConfig.LOG_FILE_MAX, String.valueOf(cfg.getDBLogFileMax()));

      if (!importConfig.appendToExistingData()) {
        if (importConfig.clearBackend() || cfg.getBaseDN().size() <= 1) {
          // We have the writer lock on the environment, now delete the
          // environment and re-open it. Only do this when we are
          // importing to all the base DNs in the backend or if the backend only
          // have one base DN.
          File parentDirectory = getFileForPath(cfg.getDBDirectory());
          File backendDirectory = new File(parentDirectory, cfg.getBackendId());
          // If the backend does not exist the import will create it.
          if (backendDirectory.exists()) {
            EnvManager.removeFiles(backendDirectory.getPath());
          }
        }
      }

      Importer importer = new Importer(importConfig, cfg, envConfig);
      rootContainer = initializeRootContainer(envConfig);
      return importer.processImport(rootContainer);
    } catch (ExecutionException execEx) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, execEx);
      }
      if (execEx.getCause() instanceof DirectoryException) {
        throw ((DirectoryException) execEx.getCause());
      } else {
        Message message = ERR_EXECUTION_ERROR.get(execEx.getMessage());
        throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message);
      }
    } catch (InterruptedException intEx) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, intEx);
      }
      Message message = ERR_INTERRUPTED_ERROR.get(intEx.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message);
    } catch (JebException je) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, je);
      }
      throw new DirectoryException(
          DirectoryServer.getServerErrorResultCode(), je.getMessageObject());
    } catch (InitializationException ie) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, ie);
      }
      throw new DirectoryException(
          DirectoryServer.getServerErrorResultCode(), ie.getMessageObject());
    } catch (ConfigException ce) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, ce);
      }
      throw new DirectoryException(
          DirectoryServer.getServerErrorResultCode(), ce.getMessageObject());
    } finally {
      // leave the backend in the same state.
      try {
        if (rootContainer != null) {
          long startTime = System.currentTimeMillis();
          rootContainer.close();
          long finishTime = System.currentTimeMillis();
          long closeTime = (finishTime - startTime) / 1000;
          Message msg = NOTE_JEB_IMPORT_LDIF_ROOTCONTAINER_CLOSE.get(closeTime);
          logError(msg);
          rootContainer = null;
        }

        // Sync the environment to disk.
        if (debugEnabled()) {
          Message message = NOTE_JEB_IMPORT_CLOSING_DATABASE.get();
          TRACER.debugInfo(message.toString());
        }
      } catch (DatabaseException de) {
        if (debugEnabled()) {
          TRACER.debugCaught(DebugLogLevel.ERROR, de);
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public LDIFImportResult importLDIF(
      LDIFImportConfig importConfig, RootContainer rootContainer, ServerContext serverContext)
      throws DirectoryException {
    try {
      ScheduledThreadPoolExecutor timerService = new ScheduledThreadPoolExecutor(1);
      try {
        final LDIFReader reader;
        try {
          reader = new LDIFReader(importConfig);
        } catch (Exception e) {
          LocalizableMessage m =
              ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_READER.get(stackTraceToSingleLineString(e));
          throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e);
        }

        long importCount = 0;
        final long startTime = System.currentTimeMillis();
        timerService.scheduleAtFixedRate(
            new ImportProgress(reader),
            IMPORT_PROGRESS_INTERVAL,
            IMPORT_PROGRESS_INTERVAL,
            TimeUnit.MILLISECONDS);
        while (true) {
          final Entry entry;
          try {
            entry = reader.readEntry();
            if (entry == null) {
              break;
            }
          } catch (LDIFException le) {
            if (!le.canContinueReading()) {
              LocalizableMessage m =
                  ERR_LDIF_BACKEND_ERROR_READING_LDIF.get(stackTraceToSingleLineString(le));
              throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, le);
            }
            continue;
          }

          final DN dn = entry.getName();
          final EntryContainer ec = rootContainer.getEntryContainer(dn);
          if (ec == null) {
            final LocalizableMessage m = ERR_LDIF_SKIP.get(dn);
            logger.error(m);
            reader.rejectLastEntry(m);
            continue;
          }

          try {
            ec.addEntry(entry, null);
            importCount++;
          } catch (DirectoryException e) {
            switch (e.getResultCode().asEnum()) {
              case ENTRY_ALREADY_EXISTS:
                if (importConfig.replaceExistingEntries()) {
                  final Entry oldEntry = ec.getEntry(entry.getName());
                  ec.replaceEntry(oldEntry, entry, null);
                } else {
                  reader.rejectLastEntry(WARN_IMPORT_ENTRY_EXISTS.get());
                }
                break;
              case NO_SUCH_OBJECT:
                reader.rejectLastEntry(ERR_IMPORT_PARENT_NOT_FOUND.get(dn.parent()));
                break;
              default:
                // Not sure why it failed.
                reader.rejectLastEntry(e.getMessageObject());
                break;
            }
          }
        }
        final long finishTime = System.currentTimeMillis();

        waitForShutdown(timerService);

        final long importTime = finishTime - startTime;
        float rate = 0;
        if (importTime > 0) {
          rate = 1000f * reader.getEntriesRead() / importTime;
        }
        logger.info(
            NOTE_IMPORT_FINAL_STATUS,
            reader.getEntriesRead(),
            importCount,
            reader.getEntriesIgnored(),
            reader.getEntriesRejected(),
            0,
            importTime / 1000,
            rate);
        return new LDIFImportResult(
            reader.getEntriesRead(), reader.getEntriesRejected(), reader.getEntriesIgnored());
      } finally {
        rootContainer.close();

        // if not already stopped, then stop it
        waitForShutdown(timerService);
      }
    } catch (DirectoryException e) {
      logger.traceException(e);
      throw e;
    } catch (OpenDsException e) {
      logger.traceException(e);
      throw new DirectoryException(getServerErrorResultCode(), e.getMessageObject());
    } catch (Exception e) {
      logger.traceException(e);
      throw new DirectoryException(
          getServerErrorResultCode(), LocalizableMessage.raw(e.getMessage()));
    }
  }
 /**
  * Provides the command-line arguments to the <CODE>configMain</CODE> method for processing.
  *
  * @param args The set of command-line arguments provided to this program.
  */
 public static void main(String[] args) {
   int exitCode = configMain(args, System.out, System.err);
   if (exitCode != 0) {
     System.exit(filterExitCode(exitCode));
   }
 }
Example #7
0
  /** {@inheritDoc} */
  @Override
  public void initializeConnectionHandler(LDAPConnectionHandlerCfg config)
      throws ConfigException, InitializationException {
    if (friendlyName == null) {
      friendlyName = config.dn().rdn().getAttributeValue(0).toString();
    }

    // Open the selector.
    try {
      selector = Selector.open();
    } catch (Exception e) {
      logger.traceException(e);

      LocalizableMessage message =
          ERR_LDAP_CONNHANDLER_OPEN_SELECTOR_FAILED.get(
              config.dn(), stackTraceToSingleLineString(e));
      throw new InitializationException(message, e);
    }

    // Save this configuration for future reference.
    currentConfig = config;
    enabled = config.isEnabled();
    requestHandlerIndex = 0;
    allowedClients = config.getAllowedClient();
    deniedClients = config.getDeniedClient();

    // Configure SSL if needed.
    try {
      // This call may disable the connector if wrong SSL settings
      configureSSL(config);
    } catch (DirectoryException e) {
      logger.traceException(e);
      throw new InitializationException(e.getMessageObject());
    }

    // Save properties that cannot be dynamically modified.
    allowReuseAddress = config.isAllowTCPReuseAddress();
    backlog = config.getAcceptBacklog();
    listenAddresses = config.getListenAddress();
    listenPort = config.getListenPort();
    numRequestHandlers = getNumRequestHandlers(config.getNumRequestHandlers(), friendlyName);

    // Construct a unique name for this connection handler, and put
    // together the set of listeners.
    listeners = new LinkedList<>();
    StringBuilder nameBuffer = new StringBuilder();
    nameBuffer.append(friendlyName);
    for (InetAddress a : listenAddresses) {
      listeners.add(new HostPort(a.getHostAddress(), listenPort));
      nameBuffer.append(" ");
      nameBuffer.append(a.getHostAddress());
    }
    nameBuffer.append(" port ");
    nameBuffer.append(listenPort);
    handlerName = nameBuffer.toString();

    // Attempt to bind to the listen port on all configured addresses to
    // verify whether the connection handler will be able to start.
    LocalizableMessage errorMessage =
        checkAnyListenAddressInUse(listenAddresses, listenPort, allowReuseAddress, config.dn());
    if (errorMessage != null) {
      logger.error(errorMessage);
      throw new InitializationException(errorMessage);
    }

    // Create a system property to store the LDAP(S) port the server is
    // listening to. This information can be displayed with jinfo.
    System.setProperty(protocol + "_port", String.valueOf(listenPort));

    // Create and start a connection finalizer thread for this
    // connection handler.
    connectionFinalizer =
        Executors.newSingleThreadScheduledExecutor(
            new DirectoryThread.Factory(
                "LDAP Connection Finalizer for connection handler " + toString()));

    connectionFinalizerActiveJobQueue = new ArrayList<>();
    connectionFinalizerPendingJobQueue = new ArrayList<>();

    connectionFinalizer.scheduleWithFixedDelay(
        new ConnectionFinalizerRunnable(), 100, 100, TimeUnit.MILLISECONDS);

    // Create and start the request handlers.
    requestHandlers = new LDAPRequestHandler[numRequestHandlers];
    for (int i = 0; i < numRequestHandlers; i++) {
      requestHandlers[i] = new LDAPRequestHandler(this, i);
    }

    for (int i = 0; i < numRequestHandlers; i++) {
      requestHandlers[i].start();
    }

    // Register the set of supported LDAP versions.
    DirectoryServer.registerSupportedLDAPVersion(3, this);
    if (config.isAllowLDAPV2()) {
      DirectoryServer.registerSupportedLDAPVersion(2, this);
    }

    // Create and register monitors.
    statTracker = new LDAPStatistics(handlerName + " Statistics");
    DirectoryServer.registerMonitorProvider(statTracker);

    connMonitor = new ClientConnectionMonitorProvider(this);
    DirectoryServer.registerMonitorProvider(connMonitor);

    // Register this as a change listener.
    config.addLDAPChangeListener(this);
  }
  private void testGetOldestNewestCSNs(final int max, final int counterWindow) throws Exception {
    String tn = "testDBCount(" + max + "," + counterWindow + ")";
    debugInfo(tn, "Starting test");

    File testRoot = null;
    ReplicationServer replicationServer = null;
    ReplicationDbEnv dbEnv = null;
    JEReplicaDB replicaDB = null;
    try {
      TestCaseUtils.startServer();
      replicationServer = configureReplicationServer(100000, 10);

      testRoot = createCleanDir();
      dbEnv = new ReplicationDbEnv(testRoot.getPath(), replicationServer);
      replicaDB = new JEReplicaDB(1, TEST_ROOT_DN, replicationServer, dbEnv);
      replicaDB.setCounterRecordWindowSize(counterWindow);

      // Populate the db with 'max' msg
      int mySeqnum = 1;
      CSN csns[] = new CSN[2 * (max + 1)];
      long now = System.currentTimeMillis();
      for (int i = 1; i <= max; i++) {
        csns[i] = new CSN(now + i, mySeqnum, 1);
        replicaDB.add(new DeleteMsg(TEST_ROOT_DN, csns[i], "uid"));
        mySeqnum += 2;
      }

      assertEquals(replicaDB.getOldestCSN(), csns[1], "Wrong oldest CSN");
      assertEquals(replicaDB.getNewestCSN(), csns[max], "Wrong newest CSN");

      // Now we want to test that after closing and reopening the db, the
      // counting algo is well reinitialized and when new messages are added
      // the new counter are correctly generated.
      debugInfo(tn, "SHUTDOWN replicaDB and recreate");
      replicaDB.shutdown();

      replicaDB = new JEReplicaDB(1, TEST_ROOT_DN, replicationServer, dbEnv);
      replicaDB.setCounterRecordWindowSize(counterWindow);

      assertEquals(replicaDB.getOldestCSN(), csns[1], "Wrong oldest CSN");
      assertEquals(replicaDB.getNewestCSN(), csns[max], "Wrong newest CSN");

      // Populate the db with 'max' msg
      for (int i = max + 1; i <= 2 * max; i++) {
        csns[i] = new CSN(now + i, mySeqnum, 1);
        replicaDB.add(new DeleteMsg(TEST_ROOT_DN, csns[i], "uid"));
        mySeqnum += 2;
      }

      assertEquals(replicaDB.getOldestCSN(), csns[1], "Wrong oldest CSN");
      assertEquals(replicaDB.getNewestCSN(), csns[2 * max], "Wrong newest CSN");

      replicaDB.purgeUpTo(new CSN(Long.MAX_VALUE, 0, 0));

      String testcase = "AFTER PURGE (oldest, newest)=";
      debugInfo(tn, testcase + replicaDB.getOldestCSN() + replicaDB.getNewestCSN());
      assertEquals(replicaDB.getNewestCSN(), csns[2 * max], "Newest=");

      // Clear ...
      debugInfo(tn, "clear:");
      replicaDB.clear();

      // Check the db is cleared.
      assertEquals(null, replicaDB.getOldestCSN());
      assertEquals(null, replicaDB.getNewestCSN());
      debugInfo(tn, "Success");
    } finally {
      shutdown(replicaDB);
      if (dbEnv != null) {
        dbEnv.shutdown();
      }
      remove(replicationServer);
      TestCaseUtils.deleteDirectory(testRoot);
    }
  }
  @DataProvider
  Object[][] cursorData() {
    // create 7 csns
    final CSN[] sevenCsns = generateCSNs(1, System.currentTimeMillis(), 7);
    CSN beforeCsn = sevenCsns[0];
    CSN middleCsn = sevenCsns[3]; // will be between csns[1] and csns[2]
    CSN afterCsn = sevenCsns[6];

    // but use only 4 of them for update msg
    // beforeCsn, middleCsn and afterCsn are not used
    // in order to test cursor generation from a key not present in the log (before, in the middle,
    // after)
    final List<CSN> usedCsns = new ArrayList<CSN>(Arrays.asList(sevenCsns));
    usedCsns.remove(beforeCsn);
    usedCsns.remove(middleCsn);
    usedCsns.remove(afterCsn);
    final CSN[] csns = usedCsns.toArray(new CSN[4]);

    return new Object[][] {
      // equal matching
      {csns, beforeCsn, EQUAL_TO_KEY, ON_MATCHING_KEY, -1, -1},
      {csns, csns[0], EQUAL_TO_KEY, ON_MATCHING_KEY, 0, 3},
      {csns, csns[1], EQUAL_TO_KEY, ON_MATCHING_KEY, 1, 3},
      {csns, middleCsn, EQUAL_TO_KEY, ON_MATCHING_KEY, -1, -1},
      {csns, csns[2], EQUAL_TO_KEY, ON_MATCHING_KEY, 2, 3},
      {csns, csns[3], EQUAL_TO_KEY, ON_MATCHING_KEY, 3, 3},
      {csns, afterCsn, EQUAL_TO_KEY, ON_MATCHING_KEY, -1, -1},
      {csns, beforeCsn, EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, csns[0], EQUAL_TO_KEY, AFTER_MATCHING_KEY, 1, 3},
      {csns, csns[1], EQUAL_TO_KEY, AFTER_MATCHING_KEY, 2, 3},
      {csns, middleCsn, EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, csns[2], EQUAL_TO_KEY, AFTER_MATCHING_KEY, 3, 3},
      {csns, csns[3], EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, afterCsn, EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},

      // less than or equal matching
      {csns, beforeCsn, LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, -1, -1},
      {csns, csns[0], LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 0, 3},
      {csns, csns[1], LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 1, 3},
      {csns, middleCsn, LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 1, 3},
      {csns, csns[2], LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 2, 3},
      {csns, csns[3], LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 3, 3},
      {csns, afterCsn, LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 3, 3},
      {csns, beforeCsn, LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, csns[0], LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 1, 3},
      {csns, csns[1], LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 2, 3},
      {csns, middleCsn, LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 2, 3},
      {csns, csns[2], LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 3, 3},
      {csns, csns[3], LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, afterCsn, LESS_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},

      // greater than or equal matching
      {csns, beforeCsn, GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 0, 3},
      {csns, csns[0], GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 0, 3},
      {csns, csns[1], GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 1, 3},
      {csns, middleCsn, GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 2, 3},
      {csns, csns[2], GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 2, 3},
      {csns, csns[3], GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, 3, 3},
      {csns, afterCsn, GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, -1, -1},
      {csns, beforeCsn, GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 0, 3},
      {csns, csns[0], GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 1, 3},
      {csns, csns[1], GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 2, 3},
      {csns, middleCsn, GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 2, 3},
      {csns, csns[2], GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, 3, 3},
      {csns, csns[3], GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {csns, afterCsn, GREATER_THAN_OR_EQUAL_TO_KEY, AFTER_MATCHING_KEY, -1, -1},
      {null, null, null, null, -1, -1} // stop line
    };
  }