Search in sources :

Example 11 with FixedRateBarrier

use of com.unboundid.util.FixedRateBarrier in project ldapsdk by pingidentity.

the class SearchAndModRate method doToolProcessing.

/**
 * Performs the actual processing for this tool.  In this case, it gets a
 * connection to the directory server and uses it to perform the requested
 * searches.
 *
 * @return  The result code for the processing that was performed.
 */
@Override()
@NotNull()
public ResultCode doToolProcessing() {
    // variable rate data file and return.
    if (sampleRateFile.isPresent()) {
        try {
            RateAdjustor.writeSampleVariableRateFile(sampleRateFile.getValue());
            return ResultCode.SUCCESS;
        } catch (final Exception e) {
            Debug.debugException(e);
            err("An error occurred while trying to write sample variable data " + "rate file '", sampleRateFile.getValue().getAbsolutePath(), "':  ", StaticUtils.getExceptionMessage(e));
            return ResultCode.LOCAL_ERROR;
        }
    }
    // Determine the random seed to use.
    final Long seed;
    if (randomSeed.isPresent()) {
        seed = Long.valueOf(randomSeed.getValue());
    } else {
        seed = null;
    }
    // Create value patterns for the base DN, filter, and proxied authorization
    // DN.
    final ValuePattern dnPattern;
    try {
        dnPattern = new ValuePattern(baseDN.getValue(), seed);
    } catch (final ParseException pe) {
        Debug.debugException(pe);
        err("Unable to parse the base DN value pattern:  ", pe.getMessage());
        return ResultCode.PARAM_ERROR;
    }
    final ValuePattern filterPattern;
    try {
        filterPattern = new ValuePattern(filter.getValue(), seed);
    } catch (final ParseException pe) {
        Debug.debugException(pe);
        err("Unable to parse the filter pattern:  ", pe.getMessage());
        return ResultCode.PARAM_ERROR;
    }
    final ValuePattern authzIDPattern;
    if (proxyAs.isPresent()) {
        try {
            authzIDPattern = new ValuePattern(proxyAs.getValue(), seed);
        } catch (final ParseException pe) {
            Debug.debugException(pe);
            err("Unable to parse the proxied authorization pattern:  ", pe.getMessage());
            return ResultCode.PARAM_ERROR;
        }
    } else {
        authzIDPattern = null;
    }
    // Get the set of controls to include in search requests.
    final ArrayList<Control> searchControls = new ArrayList<>(5);
    if (searchAssertionFilter.isPresent()) {
        searchControls.add(new AssertionRequestControl(searchAssertionFilter.getValue()));
    }
    if (searchControl.isPresent()) {
        searchControls.addAll(searchControl.getValues());
    }
    // Get the set of controls to include in modify requests.
    final ArrayList<Control> modifyControls = new ArrayList<>(5);
    if (modifyAssertionFilter.isPresent()) {
        modifyControls.add(new AssertionRequestControl(modifyAssertionFilter.getValue()));
    }
    if (permissiveModify.isPresent()) {
        modifyControls.add(new PermissiveModifyRequestControl());
    }
    if (preReadAttribute.isPresent()) {
        final List<String> attrList = preReadAttribute.getValues();
        final String[] attrArray = new String[attrList.size()];
        attrList.toArray(attrArray);
        modifyControls.add(new PreReadRequestControl(attrArray));
    }
    if (postReadAttribute.isPresent()) {
        final List<String> attrList = postReadAttribute.getValues();
        final String[] attrArray = new String[attrList.size()];
        attrList.toArray(attrArray);
        modifyControls.add(new PostReadRequestControl(attrArray));
    }
    if (modifyControl.isPresent()) {
        modifyControls.addAll(modifyControl.getValues());
    }
    // Get the attributes to return.
    final String[] returnAttrs;
    if (returnAttributes.isPresent()) {
        final List<String> attrList = returnAttributes.getValues();
        returnAttrs = new String[attrList.size()];
        attrList.toArray(returnAttrs);
    } else {
        returnAttrs = StaticUtils.NO_STRINGS;
    }
    // Get the names of the attributes to modify.
    final String[] modAttrs = new String[modifyAttributes.getValues().size()];
    modifyAttributes.getValues().toArray(modAttrs);
    // Get the character set as a byte array.
    final byte[] charSet = StaticUtils.getBytes(characterSet.getValue());
    // If the --ratePerSecond option was specified, then limit the rate
    // accordingly.
    FixedRateBarrier fixedRateBarrier = null;
    if (ratePerSecond.isPresent() || variableRateData.isPresent()) {
        // We might not have a rate per second if --variableRateData is specified.
        // The rate typically doesn't matter except when we have warm-up
        // intervals.  In this case, we'll run at the max rate.
        final int intervalSeconds = collectionInterval.getValue();
        final int ratePerInterval = (ratePerSecond.getValue() == null) ? Integer.MAX_VALUE : ratePerSecond.getValue() * intervalSeconds;
        fixedRateBarrier = new FixedRateBarrier(1000L * intervalSeconds, ratePerInterval);
    }
    // If --variableRateData was specified, then initialize a RateAdjustor.
    RateAdjustor rateAdjustor = null;
    if (variableRateData.isPresent()) {
        try {
            rateAdjustor = RateAdjustor.newInstance(fixedRateBarrier, ratePerSecond.getValue(), variableRateData.getValue());
        } catch (final IOException | IllegalArgumentException e) {
            Debug.debugException(e);
            err("Initializing the variable rates failed: " + e.getMessage());
            return ResultCode.PARAM_ERROR;
        }
    }
    // Determine whether to include timestamps in the output and if so what
    // format should be used for them.
    final boolean includeTimestamp;
    final String timeFormat;
    if (timestampFormat.getValue().equalsIgnoreCase("with-date")) {
        includeTimestamp = true;
        timeFormat = "dd/MM/yyyy HH:mm:ss";
    } else if (timestampFormat.getValue().equalsIgnoreCase("without-date")) {
        includeTimestamp = true;
        timeFormat = "HH:mm:ss";
    } else {
        includeTimestamp = false;
        timeFormat = null;
    }
    // Determine whether any warm-up intervals should be run.
    final long totalIntervals;
    final boolean warmUp;
    int remainingWarmUpIntervals = warmUpIntervals.getValue();
    if (remainingWarmUpIntervals > 0) {
        warmUp = true;
        totalIntervals = 0L + numIntervals.getValue() + remainingWarmUpIntervals;
    } else {
        warmUp = true;
        totalIntervals = 0L + numIntervals.getValue();
    }
    // Create the table that will be used to format the output.
    final OutputFormat outputFormat;
    if (csvFormat.isPresent()) {
        outputFormat = OutputFormat.CSV;
    } else {
        outputFormat = OutputFormat.COLUMNS;
    }
    final ColumnFormatter formatter = new ColumnFormatter(includeTimestamp, timeFormat, outputFormat, " ", new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Searches/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Srch Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Mods/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Mod Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Recent", "Errors/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Searches/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Srch Dur ms"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Mods/Sec"), new FormattableColumn(12, HorizontalAlignment.RIGHT, "Overall", "Mod Dur ms"));
    // Create values to use for statistics collection.
    final AtomicLong searchCounter = new AtomicLong(0L);
    final AtomicLong errorCounter = new AtomicLong(0L);
    final AtomicLong modCounter = new AtomicLong(0L);
    final AtomicLong modDurations = new AtomicLong(0L);
    final AtomicLong searchDurations = new AtomicLong(0L);
    final ResultCodeCounter rcCounter = new ResultCodeCounter();
    // Determine the length of each interval in milliseconds.
    final long intervalMillis = 1000L * collectionInterval.getValue();
    // Create the threads to use for the searches.
    final Random random = new Random();
    final CyclicBarrier barrier = new CyclicBarrier(numThreads.getValue() + 1);
    final SearchAndModRateThread[] threads = new SearchAndModRateThread[numThreads.getValue()];
    for (int i = 0; i < threads.length; i++) {
        final LDAPConnection connection;
        try {
            connection = getConnection();
        } catch (final LDAPException le) {
            Debug.debugException(le);
            err("Unable to connect to the directory server:  ", StaticUtils.getExceptionMessage(le));
            return le.getResultCode();
        }
        threads[i] = new SearchAndModRateThread(this, i, connection, dnPattern, scopeArg.getValue(), filterPattern, returnAttrs, modAttrs, valueLength.getValue(), charSet, authzIDPattern, simplePageSize.getValue(), searchControls, modifyControls, iterationsBeforeReconnect.getValue(), random.nextLong(), runningThreads, barrier, searchCounter, modCounter, searchDurations, modDurations, errorCounter, rcCounter, fixedRateBarrier);
        threads[i].start();
    }
    // Display the table header.
    for (final String headerLine : formatter.getHeaderLines(true)) {
        out(headerLine);
    }
    // which case, we'll start it after the warm-up is complete.
    if ((rateAdjustor != null) && (remainingWarmUpIntervals <= 0)) {
        rateAdjustor.start();
    }
    // Indicate that the threads can start running.
    try {
        barrier.await();
    } catch (final Exception e) {
        Debug.debugException(e);
    }
    long overallStartTime = System.nanoTime();
    long nextIntervalStartTime = System.currentTimeMillis() + intervalMillis;
    boolean setOverallStartTime = false;
    long lastSearchDuration = 0L;
    long lastModDuration = 0L;
    long lastNumErrors = 0L;
    long lastNumSearches = 0L;
    long lastNumMods = 0L;
    long lastEndTime = System.nanoTime();
    for (long i = 0; i < totalIntervals; i++) {
        if (rateAdjustor != null) {
            if (!rateAdjustor.isAlive()) {
                out("All of the rates in " + variableRateData.getValue().getName() + " have been completed.");
                break;
            }
        }
        final long startTimeMillis = System.currentTimeMillis();
        final long sleepTimeMillis = nextIntervalStartTime - startTimeMillis;
        nextIntervalStartTime += intervalMillis;
        if (sleepTimeMillis > 0) {
            sleeper.sleep(sleepTimeMillis);
        }
        if (stopRequested.get()) {
            break;
        }
        final long endTime = System.nanoTime();
        final long intervalDuration = endTime - lastEndTime;
        final long numSearches;
        final long numMods;
        final long numErrors;
        final long totalSearchDuration;
        final long totalModDuration;
        if (warmUp && (remainingWarmUpIntervals > 0)) {
            numSearches = searchCounter.getAndSet(0L);
            numMods = modCounter.getAndSet(0L);
            numErrors = errorCounter.getAndSet(0L);
            totalSearchDuration = searchDurations.getAndSet(0L);
            totalModDuration = modDurations.getAndSet(0L);
        } else {
            numSearches = searchCounter.get();
            numMods = modCounter.get();
            numErrors = errorCounter.get();
            totalSearchDuration = searchDurations.get();
            totalModDuration = modDurations.get();
        }
        final long recentNumSearches = numSearches - lastNumSearches;
        final long recentNumMods = numMods - lastNumMods;
        final long recentNumErrors = numErrors - lastNumErrors;
        final long recentSearchDuration = totalSearchDuration - lastSearchDuration;
        final long recentModDuration = totalModDuration - lastModDuration;
        final double numSeconds = intervalDuration / 1_000_000_000.0d;
        final double recentSearchRate = recentNumSearches / numSeconds;
        final double recentModRate = recentNumMods / numSeconds;
        final double recentErrorRate = recentNumErrors / numSeconds;
        final double recentAvgSearchDuration;
        if (recentNumSearches > 0L) {
            recentAvgSearchDuration = 1.0d * recentSearchDuration / recentNumSearches / 1_000_000;
        } else {
            recentAvgSearchDuration = 0.0d;
        }
        final double recentAvgModDuration;
        if (recentNumMods > 0L) {
            recentAvgModDuration = 1.0d * recentModDuration / recentNumMods / 1_000_000;
        } else {
            recentAvgModDuration = 0.0d;
        }
        if (warmUp && (remainingWarmUpIntervals > 0)) {
            out(formatter.formatRow(recentSearchRate, recentAvgSearchDuration, recentModRate, recentAvgModDuration, recentErrorRate, "warming up", "warming up", "warming up", "warming up"));
            remainingWarmUpIntervals--;
            if (remainingWarmUpIntervals == 0) {
                out("Warm-up completed.  Beginning overall statistics collection.");
                setOverallStartTime = true;
                if (rateAdjustor != null) {
                    rateAdjustor.start();
                }
            }
        } else {
            if (setOverallStartTime) {
                overallStartTime = lastEndTime;
                setOverallStartTime = false;
            }
            final double numOverallSeconds = (endTime - overallStartTime) / 1_000_000_000.0d;
            final double overallSearchRate = numSearches / numOverallSeconds;
            final double overallModRate = numMods / numOverallSeconds;
            final double overallAvgSearchDuration;
            if (numSearches > 0L) {
                overallAvgSearchDuration = 1.0d * totalSearchDuration / numSearches / 1_000_000;
            } else {
                overallAvgSearchDuration = 0.0d;
            }
            final double overallAvgModDuration;
            if (numMods > 0L) {
                overallAvgModDuration = 1.0d * totalModDuration / numMods / 1_000_000;
            } else {
                overallAvgModDuration = 0.0d;
            }
            out(formatter.formatRow(recentSearchRate, recentAvgSearchDuration, recentModRate, recentAvgModDuration, recentErrorRate, overallSearchRate, overallAvgSearchDuration, overallModRate, overallAvgModDuration));
            lastNumSearches = numSearches;
            lastNumMods = numMods;
            lastNumErrors = numErrors;
            lastSearchDuration = totalSearchDuration;
            lastModDuration = totalModDuration;
        }
        final List<ObjectPair<ResultCode, Long>> rcCounts = rcCounter.getCounts(true);
        if ((!suppressErrors.isPresent()) && (!rcCounts.isEmpty())) {
            err("\tError Results:");
            for (final ObjectPair<ResultCode, Long> p : rcCounts) {
                err("\t", p.getFirst().getName(), ":  ", p.getSecond());
            }
        }
        lastEndTime = endTime;
    }
    // Shut down the RateAdjustor if we have one.
    if (rateAdjustor != null) {
        rateAdjustor.shutDown();
    }
    // Stop all of the threads.
    ResultCode resultCode = ResultCode.SUCCESS;
    for (final SearchAndModRateThread t : threads) {
        final ResultCode r = t.stopRunning();
        if (resultCode == ResultCode.SUCCESS) {
            resultCode = r;
        }
    }
    return resultCode;
}
Also used : ValuePattern(com.unboundid.util.ValuePattern) ArrayList(java.util.ArrayList) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) Control(com.unboundid.ldap.sdk.Control) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) PreReadRequestControl(com.unboundid.ldap.sdk.controls.PreReadRequestControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) AssertionRequestControl(com.unboundid.ldap.sdk.controls.AssertionRequestControl) FormattableColumn(com.unboundid.util.FormattableColumn) Random(java.util.Random) ColumnFormatter(com.unboundid.util.ColumnFormatter) OutputFormat(com.unboundid.util.OutputFormat) RateAdjustor(com.unboundid.util.RateAdjustor) IOException(java.io.IOException) LDAPConnection(com.unboundid.ldap.sdk.LDAPConnection) ResultCodeCounter(com.unboundid.util.ResultCodeCounter) ParseException(java.text.ParseException) ArgumentException(com.unboundid.util.args.ArgumentException) LDAPException(com.unboundid.ldap.sdk.LDAPException) IOException(java.io.IOException) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicLong(java.util.concurrent.atomic.AtomicLong) LDAPException(com.unboundid.ldap.sdk.LDAPException) AtomicLong(java.util.concurrent.atomic.AtomicLong) FixedRateBarrier(com.unboundid.util.FixedRateBarrier) ParseException(java.text.ParseException) PostReadRequestControl(com.unboundid.ldap.sdk.controls.PostReadRequestControl) ResultCode(com.unboundid.ldap.sdk.ResultCode) ObjectPair(com.unboundid.util.ObjectPair) NotNull(com.unboundid.util.NotNull)

Example 12 with FixedRateBarrier

use of com.unboundid.util.FixedRateBarrier in project ldapsdk by pingidentity.

the class ParallelUpdate method doToolProcessing.

/**
 * {@inheritDoc}
 */
@Override()
@NotNull()
public ResultCode doToolProcessing() {
    // Create the sets of controls to include in each type of request.
    final Control[] addControls;
    final Control[] deleteControls;
    final Control[] modifyControls;
    final Control[] modifyDNControls;
    try {
        final List<Control> addControlList = new ArrayList<>();
        final List<Control> deleteControlList = new ArrayList<>();
        final List<Control> modifyControlList = new ArrayList<>();
        final List<Control> modifyDNControlList = new ArrayList<>();
        getOperationControls(addControlList, deleteControlList, modifyControlList, modifyDNControlList);
        addControls = StaticUtils.toArray(addControlList, Control.class);
        deleteControls = StaticUtils.toArray(deleteControlList, Control.class);
        modifyControls = StaticUtils.toArray(modifyControlList, Control.class);
        modifyDNControls = StaticUtils.toArray(modifyDNControlList, Control.class);
    } catch (final LDAPException e) {
        Debug.debugException(e);
        logCompletionMessage(true, e.getMessage());
        return e.getResultCode();
    }
    // Get the connection pool to use to communicate with the directory
    // server(s).
    final LDAPConnectionPool connectionPool;
    final int numThreads = numThreadsArg.getValue();
    try {
        connectionPool = getConnectionPool(numThreads, numThreads, 1, null, null, true, null);
        connectionPool.setConnectionPoolName("parallel-update");
        connectionPool.setRetryFailedOperationsDueToInvalidConnections((!neverRetryArg.isPresent()));
    } catch (final LDAPException e) {
        Debug.debugException(e);
        logCompletionMessage(true, ERR_PARALLEL_UPDATE_CANNOT_CREATE_POOL.get(StaticUtils.getExceptionMessage(e)));
        return e.getResultCode();
    }
    // Create the LDIF reader that will read the changes to process.
    final LDIFReader ldifReader;
    final String encryptionPassphrase;
    try {
        final ObjectPair<LDIFReader, String> ldifReaderPair = createLDIFReader();
        ldifReader = ldifReaderPair.getFirst();
        encryptionPassphrase = ldifReaderPair.getSecond();
    } catch (final LDAPException e) {
        Debug.debugException(e);
        logCompletionMessage(true, e.getMessage());
        connectionPool.close();
        return e.getResultCode();
    }
    final AtomicReference<ResultCode> resultCodeRef = new AtomicReference<>(ResultCode.SUCCESS);
    try {
        // If the LDIF file is encrypted, then get the ID of the encryption
        // settings definition (if any) used to generate the encryption key.
        final String encryptionSettingsDefinitionID;
        if (encryptionPassphrase == null) {
            encryptionSettingsDefinitionID = null;
        } else {
            encryptionSettingsDefinitionID = getEncryptionSettingsDefinitionID();
        }
        // Create the LDIF writer that will be used to write rejects.
        try {
            rejectWriter = createRejectWriter(encryptionPassphrase, encryptionSettingsDefinitionID);
        } catch (final LDAPException e) {
            Debug.debugException(e);
            logCompletionMessage(true, e.getMessage());
            return ResultCode.LOCAL_ERROR;
        }
        // log of the changes that are attempted.
        if (logFileArg.isPresent()) {
            try {
                logWriter = new PrintWriter(logFileArg.getValue());
            } catch (final Exception e) {
                Debug.debugException(e);
                logCompletionMessage(true, ERR_PARALLEL_UPDATE_ERROR_CREATING_LOG_WRITER.get(logFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e)));
                return ResultCode.LOCAL_ERROR;
            }
        }
        // Create The queue that will hold the operations to process.
        final ParallelUpdateOperationQueue operationQueue = new ParallelUpdateOperationQueue(this, numThreads, (2 * numThreads));
        // Create the rate limiter, if appropriate.
        if (ratePerSecondArg.isPresent()) {
            rateLimiter = new FixedRateBarrier(1000L, ratePerSecondArg.getValue());
        } else {
            rateLimiter = null;
        }
        // Create and start all of the threads that will be used to process
        // requests.
        final List<ParallelUpdateOperationThread> operationThreadList = new ArrayList<>(numThreads);
        for (int i = 1; i <= numThreads; i++) {
            final ParallelUpdateOperationThread operationThread = new ParallelUpdateOperationThread(this, connectionPool, operationQueue, i, rateLimiter, addControls, deleteControls, modifyControls, modifyDNControls, allowUndeleteArg.isPresent());
            operationThreadList.add(operationThread);
            operationThread.start();
        }
        // Create a progress monitor that will be used to report periodic status
        // updates about the processing that has been performed.
        final ParallelUpdateProgressMonitor progressMonitor = new ParallelUpdateProgressMonitor(this);
        try {
            processingStartTimeMillis = System.currentTimeMillis();
            progressMonitor.start();
            while (!shouldAbort.get()) {
                final LDIFChangeRecord changeRecord;
                try {
                    changeRecord = ldifReader.readChangeRecord(defaultAddArg.isPresent());
                } catch (final LDIFException e) {
                    Debug.debugException(e);
                    if (e.mayContinueReading()) {
                        final String message = ERR_PARALLEL_UPDATE_RECOVERABLE_LDIF_EXCEPTION.get(ldifFileArg.getValue().getAbsolutePath(), e.getMessage());
                        logMessage(message);
                        reject(null, new LDAPException(ResultCode.DECODING_ERROR, message, e));
                        opsAttempted.incrementAndGet();
                        continue;
                    } else {
                        shouldAbort.set(true);
                        final String message = ERR_PARALLEL_UPDATE_UNRECOVERABLE_LDIF_EXCEPTION.get(ldifFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e));
                        reject(null, new LDAPException(ResultCode.DECODING_ERROR, message, e));
                        logCompletionMessage(true, message);
                        return ResultCode.DECODING_ERROR;
                    }
                } catch (final Exception e) {
                    Debug.debugException(e);
                    shouldAbort.set(true);
                    final String message = ERR_PARALLEL_UPDATE_ERROR_READING_LDIF_FILE.get(ldifFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e));
                    reject(null, new LDAPException(ResultCode.LOCAL_ERROR, message, e));
                    logCompletionMessage(true, message);
                    return ResultCode.LOCAL_ERROR;
                }
                if (changeRecord == null) {
                    // We've reached the end of the LDIF file.
                    break;
                } else {
                    try {
                        operationQueue.addChangeRecord(changeRecord);
                    } catch (final Exception e) {
                        Debug.debugException(e);
                        // This indicates that the attempt to enqueue the change record
                        // was interrupted.  This shouldn't happen, but if it does, then
                        // mark it to be retried.
                        final LDAPException le = new LDAPException(ResultCode.LOCAL_ERROR, ERR_PARALLEL_UPDATE_ENQUEUE_FAILED.get(StaticUtils.getExceptionMessage(e)), e);
                        retry(changeRecord, le);
                    }
                }
            }
            // If a failure was encountered, then abort.
            if (shouldAbort.get()) {
                resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
                return resultCodeRef.get();
            }
            // Indicate that we've reached the end of the LDIF file.
            out();
            wrapOut(0, WRAP_COLUMN, INFO_PARALLEL_UPDATE_END_OF_LDIF.get());
            out();
            // Wait for the operation queue to become idle so that we know there
            // are no more outstanding operations to be processed.
            operationQueue.waitUntilIdle();
            initialAttempted = opsAttempted.get();
            initialSucceeded = opsSucceeded.get();
            // If there are any operations to retry, then do so now.
            Map<DN, List<ObjectPair<LDIFChangeRecord, LDAPException>>> retryQueueCopy;
            synchronized (retryQueue) {
                retryQueueCopy = new TreeMap<>(retryQueue);
                retryQueue.clear();
            }
            int lastRetryQueueSize = 0;
            while ((!retryQueueCopy.isEmpty()) && (retryQueueCopy.size() != lastRetryQueueSize)) {
                out();
                wrapOut(0, WRAP_COLUMN, INFO_PARALLEL_UPDATE_BEGINNING_RETRY.get(retryQueueCopy.size()));
                out();
                for (final Map.Entry<DN, List<ObjectPair<LDIFChangeRecord, LDAPException>>> e : retryQueueCopy.entrySet()) {
                    for (final ObjectPair<LDIFChangeRecord, LDAPException> p : e.getValue()) {
                        if (shouldAbort.get()) {
                            resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
                            return resultCodeRef.get();
                        }
                        final LDIFChangeRecord changeRecord = p.getFirst();
                        try {
                            operationQueue.addChangeRecord(changeRecord);
                            retryQueueSize.decrementAndGet();
                        } catch (final Exception ex) {
                            Debug.debugException(ex);
                            // This indicates that the attempt to enqueue the change record
                            // was interrupted.  This shouldn't happen, but if it does, then
                            // mark it to be retried.
                            final LDAPException le = new LDAPException(ResultCode.LOCAL_ERROR, ERR_PARALLEL_UPDATE_ENQUEUE_FAILED.get(StaticUtils.getExceptionMessage(ex)), ex);
                            retry(changeRecord, le);
                        }
                    }
                }
                operationQueue.waitUntilIdle();
                lastRetryQueueSize = retryQueueCopy.size();
                synchronized (retryQueue) {
                    retryQueueCopy = new TreeMap<>(retryQueue);
                    retryQueue.clear();
                }
            }
            // then reject any of the remaining operations.
            synchronized (retryQueue) {
                final int remainingToRetry = retryQueueCopy.size();
                if (remainingToRetry > 0) {
                    if (remainingToRetry == 1) {
                        wrapErr(0, WRAP_COLUMN, ERR_PARALLEL_UPDATE_NO_PROGRESS_ONE.get());
                    } else {
                        wrapErr(0, WRAP_COLUMN, ERR_PARALLEL_UPDATE_NO_PROGRESS_MULTIPLE.get(remainingToRetry));
                    }
                }
                for (final Map.Entry<DN, List<ObjectPair<LDIFChangeRecord, LDAPException>>> e : retryQueueCopy.entrySet()) {
                    for (final ObjectPair<LDIFChangeRecord, LDAPException> p : e.getValue()) {
                        reject(p.getFirst(), p.getSecond());
                        retryQueueSize.decrementAndGet();
                    }
                }
            }
        } finally {
            operationQueue.setEndOfLDIF();
            operationQueue.waitUntilIdle();
            for (final ParallelUpdateOperationThread operationThread : operationThreadList) {
                try {
                    operationThread.join();
                } catch (final Exception e) {
                    Debug.debugException(e);
                    logCompletionMessage(true, ERR_PARALLEL_UPDATE_CANNOT_JOIN_THREAD.get(operationThread.getName(), StaticUtils.getExceptionMessage(e)));
                    resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
                }
            }
            try {
                progressMonitor.stopRunning();
                progressMonitor.join();
            } catch (final Exception e) {
                Debug.debugException(e);
                logCompletionMessage(true, ERR_PARALLEL_UPDATE_CANNOT_JOIN_PROGRESS_MONITOR.get(StaticUtils.getExceptionMessage(e)));
                resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
            }
        }
    } finally {
        connectionPool.close();
        if (rejectWriter != null) {
            try {
                rejectWriter.close();
            } catch (final Exception e) {
                Debug.debugException(e);
                logCompletionMessage(true, ERR_PARALLEL_UPDATE_ERROR_CLOSING_REJECT_WRITER.get(rejectFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e)));
                resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
            }
        }
        if (logWriter != null) {
            try {
                logWriter.close();
            } catch (final Exception e) {
                Debug.debugException(e);
                logCompletionMessage(true, ERR_PARALLEL_UPDATE_ERROR_CLOSING_LOG_WRITER.get(logFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e)));
                resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
            }
        }
        try {
            ldifReader.close();
        } catch (final Exception e) {
            Debug.debugException(e);
            logCompletionMessage(true, WARN_PARALLEL_UPDATE_ERROR_CLOSING_READER.get(ldifFileArg.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e)));
            resultCodeRef.compareAndSet(ResultCode.SUCCESS, ResultCode.LOCAL_ERROR);
        }
    }
    // If we've gotten here, then processing has completed.  Print some summary
    // messages and return an appropriate result code.
    final long processingDurationMillis = System.currentTimeMillis() - processingStartTimeMillis;
    final long numAttempts = opsAttempted.get();
    final long numSuccesses = opsSucceeded.get();
    final long numRejects = opsRejected.get();
    final long retryAttempts = numAttempts - initialAttempted;
    final long retrySuccesses = numSuccesses - initialSucceeded;
    out(INFO_PARALLEL_UPDATE_DONE.get(getToolName()));
    out(INFO_PARALLEL_UPDATE_SUMMARY_OPS_ATTEMPTED.get(numAttempts));
    if (retryAttempts > 0L) {
        out(INFO_PARALLEL_UPDATE_SUMMARY_INITIAL_ATTEMPTS.get(initialAttempted));
        out(INFO_PARALLEL_UPDATE_SUMMARY_RETRY_ATTEMPTS.get(retryAttempts));
    }
    out(INFO_PARALLEL_UPDATE_SUMMARY_OPS_SUCCEEDED.get(numSuccesses));
    if (retryAttempts > 0) {
        out(INFO_PARALLEL_UPDATED_OPS_SUCCEEDED_INITIAL.get(initialSucceeded));
        out(INFO_PARALLEL_UPDATED_OPS_SUCCEEDED_RETRY.get(retrySuccesses));
    }
    out(INFO_PARALLEL_UPDATE_SUMMARY_OPS_REJECTED.get(numRejects));
    out(INFO_PARALLEL_UPDATE_SUMMARY_DURATION.get(StaticUtils.millisToHumanReadableDuration(processingDurationMillis)));
    if ((numAttempts > 0L) && (processingDurationMillis > 0L)) {
        final double attemptsPerSecond = numAttempts * 1_000.0d / processingDurationMillis;
        final DecimalFormat decimalFormat = new DecimalFormat("0.000");
        out(INFO_PARALLEL_UPDATE_SUMMARY_RATE.get(decimalFormat.format(attemptsPerSecond)));
    }
    if (numRejects == 0L) {
        completionMessage.compareAndSet(null, INFO_PARALLEL_UPDATE_COMPLETION_MESSAGE_ALL_SUCCEEDED.get(getToolName()));
    } else if (numRejects == 1L) {
        completionMessage.compareAndSet(null, INFO_PARALLEL_UPDATE_COMPLETION_MESSAGE_ONE_REJECTED.get(getToolName()));
    } else {
        completionMessage.compareAndSet(null, INFO_PARALLEL_UPDATE_COMPLETION_MESSAGE_MULTIPLE_REJECTED.get(getToolName(), numRejects));
    }
    ResultCode finalResultCode = resultCodeRef.get();
    if ((finalResultCode == ResultCode.SUCCESS) && useFirstRejectResultCodeAsExitCodeArg.isPresent() && (firstRejectResultCode.get() != null)) {
        finalResultCode = firstRejectResultCode.get();
    }
    return finalResultCode;
}
Also used : DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) DN(com.unboundid.ldap.sdk.DN) Control(com.unboundid.ldap.sdk.Control) HardDeleteRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.HardDeleteRequestControl) IgnoreNoUserModificationRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.IgnoreNoUserModificationRequestControl) ProxiedAuthorizationV2RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV2RequestControl) AssuredReplicationRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.AssuredReplicationRequestControl) SuppressOperationalAttributeUpdateRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressOperationalAttributeUpdateRequestControl) NameWithEntryUUIDRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.NameWithEntryUUIDRequestControl) SoftDeleteRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteRequestControl) ReplicationRepairRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.ReplicationRepairRequestControl) ProxiedAuthorizationV1RequestControl(com.unboundid.ldap.sdk.controls.ProxiedAuthorizationV1RequestControl) OperationPurposeRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.OperationPurposeRequestControl) SuppressReferentialIntegrityUpdatesRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.SuppressReferentialIntegrityUpdatesRequestControl) PasswordUpdateBehaviorRequestControl(com.unboundid.ldap.sdk.unboundidds.controls.PasswordUpdateBehaviorRequestControl) ManageDsaITRequestControl(com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl) PermissiveModifyRequestControl(com.unboundid.ldap.sdk.controls.PermissiveModifyRequestControl) LDIFException(com.unboundid.ldif.LDIFException) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) PrintWriter(java.io.PrintWriter) LDAPConnectionPool(com.unboundid.ldap.sdk.LDAPConnectionPool) AtomicReference(java.util.concurrent.atomic.AtomicReference) LDIFException(com.unboundid.ldif.LDIFException) ArgumentException(com.unboundid.util.args.ArgumentException) LDAPException(com.unboundid.ldap.sdk.LDAPException) LDIFChangeRecord(com.unboundid.ldif.LDIFChangeRecord) LDAPException(com.unboundid.ldap.sdk.LDAPException) LDIFReader(com.unboundid.ldif.LDIFReader) FixedRateBarrier(com.unboundid.util.FixedRateBarrier) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap) ResultCode(com.unboundid.ldap.sdk.ResultCode) NotNull(com.unboundid.util.NotNull)

Aggregations

FixedRateBarrier (com.unboundid.util.FixedRateBarrier)12 LDAPException (com.unboundid.ldap.sdk.LDAPException)9 NotNull (com.unboundid.util.NotNull)9 ArgumentException (com.unboundid.util.args.ArgumentException)9 ResultCode (com.unboundid.ldap.sdk.ResultCode)8 Control (com.unboundid.ldap.sdk.Control)7 LDAPConnection (com.unboundid.ldap.sdk.LDAPConnection)7 IOException (java.io.IOException)7 ArrayList (java.util.ArrayList)7 AssertionRequestControl (com.unboundid.ldap.sdk.controls.AssertionRequestControl)5 LDAPConnectionPool (com.unboundid.ldap.sdk.LDAPConnectionPool)4 ColumnFormatter (com.unboundid.util.ColumnFormatter)4 FormattableColumn (com.unboundid.util.FormattableColumn)4 ObjectPair (com.unboundid.util.ObjectPair)4 OutputFormat (com.unboundid.util.OutputFormat)4 ASN1OctetString (com.unboundid.asn1.ASN1OctetString)3 DN (com.unboundid.ldap.sdk.DN)3 Filter (com.unboundid.ldap.sdk.Filter)3 AuthorizationIdentityRequestControl (com.unboundid.ldap.sdk.controls.AuthorizationIdentityRequestControl)3 ManageDsaITRequestControl (com.unboundid.ldap.sdk.controls.ManageDsaITRequestControl)3