Ensure that correct Grizzly MemoryManager is used for SASL and ASN1 filters.
Use perf-tool transport factory for examples as the default one creates too many threads and uses an inefficient work queue.
Cache normalized AVA attribute values for ordering and equality matches.
Use SameThreadStrategy by default and provide "org.opends.sdk.ldap.transport.useWorkerThreads" boolean property to switch to WorkerThreadStrategy.
| | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.controls.ProxiedAuthV2RequestControl; |
| | | import org.opends.sdk.requests.*; |
| | | import org.opends.sdk.responses.*; |
| | | |
| | | import com.sun.opends.sdk.tools.PerfToolTCPNIOTransportFactory; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | System.exit(1); |
| | | } |
| | | |
| | | // Use the same transport factory as the tools. |
| | | TransportFactory.setInstance(new PerfToolTCPNIOTransportFactory()); |
| | | |
| | | // Parse command line arguments. |
| | | final String localAddress = args[0]; |
| | | final int localPort = Integer.parseInt(args[1]); |
| | |
| | | import java.util.concurrent.ConcurrentSkipListMap; |
| | | import java.util.concurrent.locks.ReentrantReadWriteLock; |
| | | |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.ldif.LDIFEntryReader; |
| | | import org.opends.sdk.requests.*; |
| | | import org.opends.sdk.responses.*; |
| | | |
| | | import com.sun.opends.sdk.tools.PerfToolTCPNIOTransportFactory; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | System.exit(1); |
| | | } |
| | | |
| | | // Use the same transport factory as the tools. |
| | | TransportFactory.setInstance(new PerfToolTCPNIOTransportFactory()); |
| | | |
| | | // Parse command line arguments. |
| | | final String localAddress = args[0]; |
| | | final int localPort = Integer.parseInt(args[1]); |
| | |
| | | import org.glassfish.grizzly.Buffer; |
| | | import org.glassfish.grizzly.memory.BuffersBuffer; |
| | | import org.glassfish.grizzly.memory.CompositeBuffer; |
| | | import org.glassfish.grizzly.memory.MemoryManager; |
| | | |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | |
| | | |
| | |
| | | * @param maxElementSize |
| | | * The maximum BER element size, or <code>0</code> to indicate that |
| | | * there is no limit. |
| | | * @param memoryManager |
| | | * The memory manager to use for buffering. |
| | | */ |
| | | ASN1BufferReader(final int maxElementSize) |
| | | ASN1BufferReader(final int maxElementSize, |
| | | final MemoryManager<?> memoryManager) |
| | | { |
| | | this.readLimiter = new RootSequenceLimiter(); |
| | | this.stringBuffer = new byte[MAX_STRING_BUFFER_SIZE]; |
| | | this.maxElementSize = maxElementSize; |
| | | this.buffer = BuffersBuffer.create(); |
| | | this.buffer = BuffersBuffer.create(memoryManager); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | // The connection needs to be secured by the SASL |
| | | // mechanism. |
| | | ldapConnection.installFilter(new SASLFilter(l)); |
| | | ldapConnection.installFilter(new SASLFilter(l, ctx |
| | | .getConnection().getTransport().getMemoryManager())); |
| | | } |
| | | } |
| | | |
| | |
| | | .get(ctx.getConnection()); |
| | | if (asn1Reader == null) |
| | | { |
| | | asn1Reader = new ASN1BufferReader(maxASN1ElementSize); |
| | | asn1Reader = new ASN1BufferReader(maxASN1ElementSize, ctx.getConnection() |
| | | .getTransport().getMemoryManager()); |
| | | LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader); |
| | | } |
| | | asn1Reader.appendBytesRead(buffer); |
| | |
| | | @Override |
| | | public void startSASL(final ConnectionSecurityLayer bindContext) |
| | | { |
| | | installFilter(connection, new SASLFilter(bindContext)); |
| | | installFilter(connection, new SASLFilter(bindContext, connection |
| | | .getTransport().getMemoryManager())); |
| | | } |
| | | |
| | | |
| | |
| | | .get(ctx.getConnection()); |
| | | if (asn1Reader == null) |
| | | { |
| | | asn1Reader = new ASN1BufferReader(maxASN1ElementSize); |
| | | asn1Reader = new ASN1BufferReader(maxASN1ElementSize, ctx.getConnection() |
| | | .getTransport().getMemoryManager()); |
| | | LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader); |
| | | } |
| | | asn1Reader.appendBytesRead(buffer); |
| | |
| | | private final byte[] buffer = new byte[BUFFER_SIZE]; |
| | | private final ConnectionSecurityLayer bindContext; |
| | | |
| | | private final MemoryManager<Buffer> memoryManager; |
| | | |
| | | |
| | | |
| | | @SuppressWarnings("unchecked") |
| | | public SASLDecoderTransformer(final ConnectionSecurityLayer bindContext) |
| | | { |
| | | this(bindContext, TransportFactory.getInstance().getDefaultMemoryManager()); |
| | | } |
| | | private final MemoryManager<?> memoryManager; |
| | | |
| | | |
| | | |
| | | public SASLDecoderTransformer(final ConnectionSecurityLayer bindContext, |
| | | final MemoryManager<Buffer> memoryManager) |
| | | final MemoryManager<?> memoryManager) |
| | | { |
| | | this.bindContext = bindContext; |
| | | this.memoryManager = memoryManager; |
| | |
| | | private final byte[] buffer = new byte[BUFFER_SIZE]; |
| | | private final ConnectionSecurityLayer bindContext; |
| | | |
| | | private final MemoryManager<Buffer> memoryManager; |
| | | |
| | | |
| | | |
| | | @SuppressWarnings("unchecked") |
| | | public SASLEncoderTransformer(final ConnectionSecurityLayer bindContext) |
| | | { |
| | | this(bindContext, TransportFactory.getInstance().getDefaultMemoryManager()); |
| | | } |
| | | private final MemoryManager<?> memoryManager; |
| | | |
| | | |
| | | |
| | | public SASLEncoderTransformer(final ConnectionSecurityLayer bindContext, |
| | | final MemoryManager<Buffer> memoryManager) |
| | | final MemoryManager<?> memoryManager) |
| | | { |
| | | this.bindContext = bindContext; |
| | | this.memoryManager = memoryManager; |
| | |
| | | |
| | | import org.glassfish.grizzly.Buffer; |
| | | import org.glassfish.grizzly.filterchain.AbstractCodecFilter; |
| | | import org.glassfish.grizzly.memory.MemoryManager; |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | final class SASLFilter extends AbstractCodecFilter<Buffer, Buffer> |
| | | { |
| | | public SASLFilter(final ConnectionSecurityLayer bindContext) |
| | | public SASLFilter(final ConnectionSecurityLayer bindContext, |
| | | final MemoryManager<?> memoryManager) |
| | | { |
| | | super(new SASLDecoderTransformer(bindContext), new SASLEncoderTransformer( |
| | | bindContext)); |
| | | super(new SASLDecoderTransformer(bindContext, memoryManager), |
| | | new SASLEncoderTransformer(bindContext, memoryManager)); |
| | | } |
| | | } |
| | |
| | | |
| | | package com.sun.opends.sdk.tools; |
| | | |
| | | import com.sun.opends.sdk.util.RecursiveFutureResult; |
| | | |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.requests.*; |
| | | import org.opends.sdk.responses.BindResult; |
| | | import org.opends.sdk.responses.SearchResultEntry; |
| | | |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | import static com.sun.opends.sdk.tools.ToolConstants.*; |
| | | import static com.sun.opends.sdk.tools.Utils.filterExitCode; |
| | | |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | import static com.sun.opends.sdk.tools.ToolConstants.*; |
| | | import static com.sun.opends.sdk.tools.Utils.filterExitCode; |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.requests.*; |
| | | import org.opends.sdk.responses.BindResult; |
| | | import org.opends.sdk.responses.SearchResultEntry; |
| | | |
| | | import com.sun.opends.sdk.util.RecursiveFutureResult; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A load generation tool that can be used to load a Directory Server with |
| | | * Bind requests using one or more LDAP connections. |
| | | * A load generation tool that can be used to load a Directory Server with Bind |
| | | * requests using one or more LDAP connections. |
| | | */ |
| | | public final class AuthRate extends ConsoleApplication |
| | | { |
| | | private final class BindPerformanceRunner extends PerformanceRunner |
| | | { |
| | | private final AtomicLong searchWaitRecentTime = new AtomicLong(); |
| | | private final AtomicInteger invalidCredRecentCount = new AtomicInteger(); |
| | | |
| | | private final class BindStatsThread extends StatsThread |
| | | { |
| | | private final String[] extraColumn; |
| | | |
| | | |
| | | |
| | | private BindStatsThread(boolean extraFieldRequired) |
| | | private BindStatsThread(final boolean extraFieldRequired) |
| | | { |
| | | super(extraFieldRequired ? new String[] { "bind time %" } |
| | | : new String[0]); |
| | |
| | | private final class BindUpdateStatsResultHandler extends |
| | | UpdateStatsResultHandler<BindResult> |
| | | { |
| | | private BindUpdateStatsResultHandler(long startTime) |
| | | private BindUpdateStatsResultHandler(final long startTime, |
| | | final AsynchronousConnection connection, final ConnectionWorker worker) |
| | | { |
| | | super(startTime); |
| | | super(startTime, connection, worker); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public void handleErrorResult(ErrorResultException error) |
| | | public void handleErrorResult(final ErrorResultException error) |
| | | { |
| | | super.handleErrorResult(error); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private final class BindWorkerThread extends WorkerThread |
| | | |
| | | |
| | | private final class BindWorkerThread extends ConnectionWorker |
| | | { |
| | | private SearchRequest sr; |
| | | private BindRequest br; |
| | |
| | | private final ThreadLocal<Random> rng = new ThreadLocal<Random>() |
| | | { |
| | | |
| | | @Override |
| | | protected Random initialValue() |
| | | { |
| | | return new Random(); |
| | |
| | | }; |
| | | |
| | | |
| | | |
| | | private BindWorkerThread(final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | { |
| | |
| | | if (dataSources != null) |
| | | { |
| | | data = DataSource.generateData(dataSources, data); |
| | | if(data.length == dataSources.length) |
| | | if (data.length == dataSources.length) |
| | | { |
| | | Object[] newData = new Object[data.length + 1]; |
| | | final Object[] newData = new Object[data.length + 1]; |
| | | System.arraycopy(data, 0, newData, 0, data.length); |
| | | data = newData; |
| | | } |
| | | } |
| | | if(filter != null && baseDN != null) |
| | | if (filter != null && baseDN != null) |
| | | { |
| | | if (sr == null) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | sr = Requests.newSearchRequest(String.format(baseDN, data), scope, |
| | | String.format(filter, data), attributes); |
| | | sr = Requests.newSearchRequest(String.format(baseDN, data), |
| | | scope, String.format(filter, data), attributes); |
| | | } |
| | | sr.setDereferenceAliasesPolicy(dereferencesAliasesPolicy); |
| | | } |
| | |
| | | sr.setName(String.format(baseDN, data)); |
| | | } |
| | | |
| | | RecursiveFutureResult<SearchResultEntry, BindResult> future = |
| | | new RecursiveFutureResult<SearchResultEntry, BindResult>( |
| | | new BindUpdateStatsResultHandler(startTime)) |
| | | final RecursiveFutureResult<SearchResultEntry, BindResult> future = |
| | | new RecursiveFutureResult<SearchResultEntry, BindResult>( |
| | | new BindUpdateStatsResultHandler(startTime, connection, this)) |
| | | { |
| | | @Override |
| | | protected FutureResult<? extends BindResult> chainResult( |
| | | final SearchResultEntry innerResult, |
| | | final ResultHandler<? super BindResult> resultHandler) |
| | | throws ErrorResultException |
| | | { |
| | | searchWaitRecentTime.getAndAdd(System.nanoTime() - startTime); |
| | | if (data == null) |
| | | { |
| | | @Override |
| | | protected FutureResult<? extends BindResult> chainResult( |
| | | SearchResultEntry innerResult, |
| | | ResultHandler<? super BindResult> resultHandler) |
| | | throws ErrorResultException |
| | | { |
| | | searchWaitRecentTime.getAndAdd(System.nanoTime() - startTime); |
| | | if(data == null) |
| | | { |
| | | data = new Object[1]; |
| | | } |
| | | data[data.length-1] = innerResult.getName().toString(); |
| | | return performBind(connection, data, resultHandler); |
| | | } |
| | | }; |
| | | data = new Object[1]; |
| | | } |
| | | data[data.length - 1] = innerResult.getName().toString(); |
| | | return performBind(connection, data, resultHandler); |
| | | } |
| | | }; |
| | | connection.searchSingleEntry(sr, future); |
| | | return future; |
| | | } |
| | | else |
| | | { |
| | | return performBind(connection, data, |
| | | new BindUpdateStatsResultHandler(startTime)); |
| | | new BindUpdateStatsResultHandler(startTime, connection, this)); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | if (bindRequest instanceof SimpleBindRequest) |
| | | { |
| | | SimpleBindRequest o = (SimpleBindRequest) bindRequest; |
| | | final SimpleBindRequest o = (SimpleBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfSimpleBindRequest(o); |
| | | } |
| | | |
| | | SimpleBindRequest sbr = (SimpleBindRequest) br; |
| | | final SimpleBindRequest sbr = (SimpleBindRequest) br; |
| | | if (data != null && o.getName() != null) |
| | | { |
| | | sbr.setName(String.format(o.getName(), data)); |
| | |
| | | } |
| | | else if (bindRequest instanceof DigestMD5SASLBindRequest) |
| | | { |
| | | DigestMD5SASLBindRequest o = (DigestMD5SASLBindRequest) bindRequest; |
| | | final DigestMD5SASLBindRequest o = (DigestMD5SASLBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfDigestMD5SASLBindRequest(o); |
| | | } |
| | | |
| | | DigestMD5SASLBindRequest sbr = (DigestMD5SASLBindRequest) br; |
| | | final DigestMD5SASLBindRequest sbr = (DigestMD5SASLBindRequest) br; |
| | | if (data != null) |
| | | { |
| | | if (o.getAuthenticationID() != null) |
| | |
| | | } |
| | | else if (bindRequest instanceof CRAMMD5SASLBindRequest) |
| | | { |
| | | CRAMMD5SASLBindRequest o = (CRAMMD5SASLBindRequest) bindRequest; |
| | | final CRAMMD5SASLBindRequest o = (CRAMMD5SASLBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfCRAMMD5SASLBindRequest(o); |
| | | } |
| | | |
| | | CRAMMD5SASLBindRequest sbr = (CRAMMD5SASLBindRequest) br; |
| | | final CRAMMD5SASLBindRequest sbr = (CRAMMD5SASLBindRequest) br; |
| | | if (data != null && o.getAuthenticationID() != null) |
| | | { |
| | | sbr.setAuthenticationID(String.format(o.getAuthenticationID(), data)); |
| | |
| | | } |
| | | else if (bindRequest instanceof GSSAPISASLBindRequest) |
| | | { |
| | | GSSAPISASLBindRequest o = (GSSAPISASLBindRequest) bindRequest; |
| | | final GSSAPISASLBindRequest o = (GSSAPISASLBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfGSSAPISASLBindRequest(o); |
| | | } |
| | | |
| | | GSSAPISASLBindRequest sbr = (GSSAPISASLBindRequest) br; |
| | | final GSSAPISASLBindRequest sbr = (GSSAPISASLBindRequest) br; |
| | | if (data != null) |
| | | { |
| | | if (o.getAuthenticationID() != null) |
| | |
| | | } |
| | | else if (bindRequest instanceof ExternalSASLBindRequest) |
| | | { |
| | | ExternalSASLBindRequest o = (ExternalSASLBindRequest) bindRequest; |
| | | final ExternalSASLBindRequest o = (ExternalSASLBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfExternalSASLBindRequest(o); |
| | | } |
| | | |
| | | ExternalSASLBindRequest sbr = (ExternalSASLBindRequest) br; |
| | | final ExternalSASLBindRequest sbr = (ExternalSASLBindRequest) br; |
| | | if (data != null && o.getAuthorizationID() != null) |
| | | { |
| | | sbr.setAuthorizationID(String.format(o.getAuthorizationID(), data)); |
| | |
| | | } |
| | | else if (bindRequest instanceof PlainSASLBindRequest) |
| | | { |
| | | PlainSASLBindRequest o = (PlainSASLBindRequest) bindRequest; |
| | | final PlainSASLBindRequest o = (PlainSASLBindRequest) bindRequest; |
| | | if (br == null) |
| | | { |
| | | br = Requests.copyOfPlainSASLBindRequest(o); |
| | | } |
| | | |
| | | PlainSASLBindRequest sbr = (PlainSASLBindRequest) br; |
| | | final PlainSASLBindRequest sbr = (PlainSASLBindRequest) br; |
| | | if (data != null) |
| | | { |
| | | if (o.getAuthenticationID() != null) |
| | |
| | | |
| | | |
| | | |
| | | private final AtomicLong searchWaitRecentTime = new AtomicLong(); |
| | | |
| | | private final AtomicInteger invalidCredRecentCount = new AtomicInteger(); |
| | | |
| | | private String filter; |
| | | |
| | | private String baseDN; |
| | |
| | | |
| | | |
| | | @Override |
| | | StatsThread newStatsThread() |
| | | ConnectionWorker newConnectionWorker( |
| | | final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | { |
| | | return new BindStatsThread(filter != null && baseDN != null); |
| | | return new BindWorkerThread(connection, connectionFactory); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | WorkerThread newWorkerThread(final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | StatsThread newStatsThread() |
| | | { |
| | | return new BindWorkerThread(connection, connectionFactory); |
| | | return new BindStatsThread(filter != null && baseDN != null); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * The main method for AuthRate tool. |
| | | * |
| | |
| | | |
| | | |
| | | |
| | | |
| | | private AuthRate(final InputStream in, final OutputStream out, |
| | | final OutputStream err) |
| | | { |
| | |
| | | { |
| | | // Create the command-line argument parser for use with this |
| | | // program. |
| | | final LocalizableMessage toolDescription = |
| | | INFO_AUTHRATE_TOOL_DESCRIPTION.get(); |
| | | final ArgumentParser argParser = new ArgumentParser(AuthRate.class |
| | | .getName(), toolDescription, false, true, 0, 0, |
| | | final LocalizableMessage toolDescription = INFO_AUTHRATE_TOOL_DESCRIPTION |
| | | .get(); |
| | | final ArgumentParser argParser = new ArgumentParser( |
| | | AuthRate.class.getName(), toolDescription, false, true, 0, 0, |
| | | "[filter format string] [attributes ...]"); |
| | | |
| | | ConnectionFactoryProvider connectionFactoryProvider; |
| | |
| | | try |
| | | { |
| | | TransportFactory.setInstance(new PerfToolTCPNIOTransportFactory()); |
| | | connectionFactoryProvider = |
| | | new ConnectionFactoryProvider(argParser, this); |
| | | connectionFactoryProvider = new ConnectionFactoryProvider(argParser, this); |
| | | runner = new BindPerformanceRunner(argParser, this); |
| | | |
| | | propertiesFileArgument = new StringArgument("propertiesFilePath", null, |
| | |
| | | argParser.setUsageArgument(showUsage, getOutputStream()); |
| | | |
| | | baseDN = new StringArgument("baseDN", OPTION_SHORT_BASEDN, |
| | | OPTION_LONG_BASEDN, false, false, true, INFO_BASEDN_PLACEHOLDER.get(), |
| | | null, null, INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get()); |
| | | OPTION_LONG_BASEDN, false, false, true, |
| | | INFO_BASEDN_PLACEHOLDER.get(), null, null, |
| | | INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get()); |
| | | baseDN.setPropertyName(OPTION_LONG_BASEDN); |
| | | argParser.addArgument(baseDN); |
| | | |
| | | searchScope = new MultiChoiceArgument<SearchScope>("searchScope", 's', |
| | | "searchScope", false, true, INFO_SEARCH_SCOPE_PLACEHOLDER.get(), |
| | | SearchScope.values(), false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE |
| | | .get()); |
| | | SearchScope.values(), false, |
| | | INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get()); |
| | | searchScope.setPropertyName("searchScope"); |
| | | searchScope.setDefaultValue(SearchScope.WHOLE_SUBTREE); |
| | | argParser.addArgument(searchScope); |
| | | |
| | | dereferencePolicy = new MultiChoiceArgument<DereferenceAliasesPolicy>( |
| | | "derefpolicy", 'a', "dereferencePolicy", false, true, |
| | | INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), DereferenceAliasesPolicy |
| | | .values(), false, INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY |
| | | .get()); |
| | | INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), |
| | | DereferenceAliasesPolicy.values(), false, |
| | | INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get()); |
| | | dereferencePolicy.setPropertyName("dereferencePolicy"); |
| | | dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER); |
| | | argParser.addArgument(dereferencePolicy); |
| | | |
| | | invalidCredPercent = new IntegerArgument("invalidPassword", 'I', |
| | | "invalidPassword", false, false, true, LocalizableMessage |
| | | .raw("{invalidPassword}"), 0, null, true, 0, true, 100, |
| | | LocalizableMessage |
| | | .raw("Percent of bind operations with simulated " + |
| | | "invalid password")); |
| | | "invalidPassword", false, false, true, |
| | | LocalizableMessage.raw("{invalidPassword}"), 0, null, true, 0, true, |
| | | 100, |
| | | LocalizableMessage.raw("Percent of bind operations with simulated " |
| | | + "invalid password")); |
| | | invalidCredPercent.setPropertyName("invalidPassword"); |
| | | argParser.addArgument(invalidCredPercent); |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | connectionFactory = |
| | | connectionFactoryProvider.getConnectionFactory(); |
| | | connectionFactory = connectionFactoryProvider.getConnectionFactory(); |
| | | runner.validate(); |
| | | |
| | | runner.bindRequest = connectionFactoryProvider.getBindRequest(); |
| | | if(runner.bindRequest == null) |
| | | if (runner.bindRequest == null) |
| | | { |
| | | throw new ArgumentException(LocalizableMessage.raw( |
| | | "Authentication information must be provided to use this tool")); |
| | | throw new ArgumentException( |
| | | LocalizableMessage |
| | | .raw("Authentication information must be provided to use this tool")); |
| | | } |
| | | } |
| | | catch (final ArgumentException ae) |
| | |
| | | |
| | | // Try it out to make sure the format string and data sources |
| | | // match. |
| | | final Object[] data = DataSource.generateData(runner.getDataSources(), |
| | | null); |
| | | final Object[] data = DataSource |
| | | .generateData(runner.getDataSources(), null); |
| | | try |
| | | { |
| | | if(runner.baseDN != null && runner.filter != null) |
| | | if (runner.baseDN != null && runner.filter != null) |
| | | { |
| | | String.format(runner.filter, data); |
| | | String.format(runner.baseDN, data); |
| | |
| | | return runner.run(connectionFactory); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | private static final class ModifyPerformanceRunner extends PerformanceRunner |
| | | { |
| | | private final class ModifyWorkerThread extends WorkerThread |
| | | private final class ModifyWorkerThread extends ConnectionWorker |
| | | { |
| | | private ModifyRequest mr; |
| | | private Object[] data; |
| | |
| | | @Override |
| | | public FutureResult<?> performOperation( |
| | | final AsynchronousConnection connection, |
| | | final DataSource[] dataSources, long startTime) |
| | | final DataSource[] dataSources, final long startTime) |
| | | { |
| | | if (dataSources != null) |
| | | { |
| | | data = DataSource.generateData(dataSources, data); |
| | | } |
| | | mr = newModifyRequest(data); |
| | | return connection.modify(mr, |
| | | new UpdateStatsResultHandler<Result>(startTime)); |
| | | return connection.modify(mr, new UpdateStatsResultHandler<Result>( |
| | | startTime, connection, this)); |
| | | } |
| | | |
| | | |
| | |
| | | colonPos = formattedString.indexOf(':'); |
| | | if (colonPos > 0) |
| | | { |
| | | mr.addModification(ModificationType.REPLACE, formattedString |
| | | .substring(0, colonPos), formattedString |
| | | .substring(colonPos + 1)); |
| | | mr.addModification(ModificationType.REPLACE, |
| | | formattedString.substring(0, colonPos), |
| | | formattedString.substring(colonPos + 1)); |
| | | } |
| | | } |
| | | return mr; |
| | |
| | | |
| | | |
| | | @Override |
| | | StatsThread newStatsThread() |
| | | ConnectionWorker newConnectionWorker( |
| | | final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | { |
| | | return new StatsThread(new String[0]); |
| | | return new ModifyWorkerThread(connection, connectionFactory); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | WorkerThread newWorkerThread(final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | StatsThread newStatsThread() |
| | | { |
| | | return new ModifyWorkerThread(connection, connectionFactory); |
| | | return new StatsThread(new String[0]); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | // Create the command-line argument parser for use with this |
| | | // program. |
| | | final LocalizableMessage toolDescription = |
| | | INFO_MODRATE_TOOL_DESCRIPTION.get(); |
| | | final LocalizableMessage toolDescription = INFO_MODRATE_TOOL_DESCRIPTION |
| | | .get(); |
| | | final ArgumentParser argParser = new ArgumentParser( |
| | | ModRate.class.getName(), toolDescription, false, true, 1, 0, |
| | | "[(attribute:value format string) ...]"); |
| | |
| | | try |
| | | { |
| | | TransportFactory.setInstance(new PerfToolTCPNIOTransportFactory()); |
| | | connectionFactoryProvider = |
| | | new ConnectionFactoryProvider(argParser, this); |
| | | connectionFactoryProvider = new ConnectionFactoryProvider(argParser, this); |
| | | runner = new ModifyPerformanceRunner(argParser, this); |
| | | propertiesFileArgument = new StringArgument("propertiesFilePath", null, |
| | | OPTION_LONG_PROP_FILE_PATH, false, false, true, |
| | |
| | | argParser.setNoPropertiesFileArgument(noPropertiesFileArgument); |
| | | |
| | | baseDN = new StringArgument("targetDN", OPTION_SHORT_BASEDN, |
| | | OPTION_LONG_TARGETDN, true, false, true, INFO_TARGETDN_PLACEHOLDER.get(), |
| | | null, null, INFO_MODRATE_TOOL_DESCRIPTION_TARGETDN.get()); |
| | | OPTION_LONG_TARGETDN, true, false, true, |
| | | INFO_TARGETDN_PLACEHOLDER.get(), null, null, |
| | | INFO_MODRATE_TOOL_DESCRIPTION_TARGETDN.get()); |
| | | baseDN.setPropertyName(OPTION_LONG_BASEDN); |
| | | argParser.addArgument(baseDN); |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | connectionFactory = |
| | | connectionFactoryProvider.getAuthenticatedConnectionFactory(); |
| | | connectionFactory = connectionFactoryProvider |
| | | .getAuthenticatedConnectionFactory(); |
| | | runner.validate(); |
| | | } |
| | | catch (final ArgumentException ae) |
| | |
| | | /** |
| | | * The TCPNIOTransportFactory which performance tools will use. |
| | | */ |
| | | final class PerfToolTCPNIOTransportFactory extends DefaultNIOTransportFactory |
| | | public final class PerfToolTCPNIOTransportFactory extends |
| | | DefaultNIOTransportFactory |
| | | { |
| | | private int selectors; |
| | | |
| | |
| | | } |
| | | final String selectorsStr = System |
| | | .getProperty("org.opends.sdk.ldap.transport.selectors"); |
| | | if (threadsStr != null) |
| | | if (selectorsStr != null) |
| | | { |
| | | selectors = Integer.parseInt(selectorsStr); |
| | | } |
| | |
| | | import java.lang.management.GarbageCollectorMXBean; |
| | | import java.lang.management.ManagementFactory; |
| | | import java.util.*; |
| | | import java.util.concurrent.CountDownLatch; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | import org.opends.sdk.*; |
| | | import org.opends.sdk.responses.BindResult; |
| | | import org.opends.sdk.responses.ExtendedResult; |
| | | import org.opends.sdk.responses.Result; |
| | | |
| | | import com.sun.opends.sdk.tools.AuthenticatedConnectionFactory.AuthenticatedAsynchronousConnection; |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | abstract class PerformanceRunner implements ConnectionEventListener |
| | | { |
| | | abstract class ConnectionWorker |
| | | { |
| | | private final AtomicInteger operationsInFlight = new AtomicInteger(); |
| | | |
| | | private volatile int count; |
| | | |
| | | private final AsynchronousConnection staticConnection; |
| | | |
| | | private final ConnectionFactory connectionFactory; |
| | | |
| | | private final CountDownLatch latch = new CountDownLatch(1); |
| | | |
| | | |
| | | |
| | | ConnectionWorker(final AsynchronousConnection staticConnection, |
| | | final ConnectionFactory connectionFactory) |
| | | { |
| | | this.staticConnection = staticConnection; |
| | | this.connectionFactory = connectionFactory; |
| | | } |
| | | |
| | | |
| | | |
| | | public void operationCompleted(final AsynchronousConnection connection) |
| | | { |
| | | if (operationsInFlight.decrementAndGet() == 0 |
| | | && this.staticConnection == null) |
| | | { |
| | | connection.close(); |
| | | } |
| | | startWork(); |
| | | } |
| | | |
| | | |
| | | |
| | | public abstract FutureResult<?> performOperation( |
| | | final AsynchronousConnection connection, |
| | | final DataSource[] dataSources, final long startTime); |
| | | |
| | | |
| | | |
| | | public void startWork() |
| | | { |
| | | if (!stopRequested && !(maxIterations > 0 && count >= maxIterations)) |
| | | { |
| | | if (this.staticConnection == null) |
| | | { |
| | | connectionFactory |
| | | .getAsynchronousConnection(new ResultHandler<AsynchronousConnection>() |
| | | { |
| | | public void handleErrorResult(final ErrorResultException e) |
| | | { |
| | | app.println(LocalizableMessage.raw(e.getResult() |
| | | .getDiagnosticMessage())); |
| | | if (e.getCause() != null && app.isVerbose()) |
| | | { |
| | | e.getCause().printStackTrace(app.getErrorStream()); |
| | | } |
| | | stopRequested = true; |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleResult(final AsynchronousConnection result) |
| | | { |
| | | doWork(result); |
| | | } |
| | | }); |
| | | } |
| | | else |
| | | { |
| | | if (!noRebind |
| | | && this.staticConnection instanceof AuthenticatedAsynchronousConnection) |
| | | { |
| | | final AuthenticatedAsynchronousConnection ac = |
| | | (AuthenticatedAsynchronousConnection) this.staticConnection; |
| | | ac.rebind(new ResultHandler<BindResult>() |
| | | { |
| | | public void handleErrorResult(final ErrorResultException e) |
| | | { |
| | | app.println(LocalizableMessage.raw(e.getResult().toString())); |
| | | if (e.getCause() != null && app.isVerbose()) |
| | | { |
| | | e.getCause().printStackTrace(app.getErrorStream()); |
| | | } |
| | | stopRequested = true; |
| | | } |
| | | |
| | | |
| | | |
| | | public void handleResult(final BindResult result) |
| | | { |
| | | doWork(staticConnection); |
| | | } |
| | | }); |
| | | } |
| | | else |
| | | { |
| | | doWork(staticConnection); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | latch.countDown(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public void waitFor() throws InterruptedException |
| | | { |
| | | latch.await(); |
| | | } |
| | | |
| | | |
| | | |
| | | private void doWork(final AsynchronousConnection connection) |
| | | { |
| | | long start; |
| | | double sleepTimeInMS = 0; |
| | | final int opsToPerform = isAsync ? numConcurrentTasks : numConcurrentTasks |
| | | - operationsInFlight.get(); |
| | | for (int i = 0; i < opsToPerform; i++) |
| | | { |
| | | if (maxIterations > 0 && count >= maxIterations) |
| | | { |
| | | break; |
| | | } |
| | | start = System.nanoTime(); |
| | | performOperation(connection, dataSources.get(), start); |
| | | operationRecentCount.getAndIncrement(); |
| | | operationsInFlight.getAndIncrement(); |
| | | count++; |
| | | |
| | | if (targetThroughput > 0) |
| | | { |
| | | try |
| | | { |
| | | if (sleepTimeInMS > 1) |
| | | { |
| | | Thread.sleep((long) Math.floor(sleepTimeInMS)); |
| | | } |
| | | } |
| | | catch (final InterruptedException e) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | sleepTimeInMS += targetTimeInMS |
| | | - ((System.nanoTime() - start) / 1000000.0); |
| | | if (sleepTimeInMS < -60000) |
| | | { |
| | | // If we fall behind by 60 seconds, just forget about |
| | | // catching up |
| | | sleepTimeInMS = -60000; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Statistics thread base implementation. |
| | | */ |
| | |
| | | if (resultCount > 0) |
| | | { |
| | | strings[2] = String.format("%.3f", |
| | | (waitTime - (gcDuration - lastGCDuration)) |
| | | / (double) resultCount / 1000000.0); |
| | | (waitTime - (gcDuration - lastGCDuration)) / (double) resultCount |
| | | / 1000000.0); |
| | | } |
| | | else |
| | | { |
| | |
| | | { |
| | | // Script-friendly. |
| | | app.getOutputStream().print(averageDuration); |
| | | for (String s : strings) |
| | | for (final String s : strings) |
| | | { |
| | | app.getOutputStream().print(","); |
| | | app.getOutputStream().print(s); |
| | |
| | | class UpdateStatsResultHandler<S extends Result> implements ResultHandler<S> |
| | | { |
| | | private final long startTime; |
| | | private final AsynchronousConnection connection; |
| | | private final ConnectionWorker worker; |
| | | |
| | | |
| | | |
| | | UpdateStatsResultHandler(final long startTime) |
| | | UpdateStatsResultHandler(final long startTime, |
| | | final AsynchronousConnection connection, final ConnectionWorker worker) |
| | | { |
| | | this.startTime = startTime; |
| | | this.connection = connection; |
| | | this.worker = worker; |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | app.println(LocalizableMessage.raw(error.getResult().toString())); |
| | | } |
| | | |
| | | worker.operationCompleted(connection); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | successRecentCount.getAndIncrement(); |
| | | updateStats(); |
| | | worker.operationCompleted(connection); |
| | | } |
| | | |
| | | |
| | |
| | | AsynchronousConnection connection; |
| | | |
| | | final double targetTimeInMS = |
| | | (1.0 / (targetThroughput / |
| | | (double) (numThreads * numConnections))) * 1000.0; |
| | | (1.0 / (targetThroughput / (double) (numConcurrentTasks * numConnections))) * 1000.0; |
| | | double sleepTimeInMS = 0; |
| | | long start; |
| | | while (!stopRequested && !(maxIterations > 0 && count >= maxIterations)) |
| | |
| | | |
| | | private final AtomicLong waitRecentTime = new AtomicLong(); |
| | | |
| | | private final AtomicReference<ReversableArray> eTimeBuffer = |
| | | new AtomicReference<ReversableArray>(new ReversableArray(100000)); |
| | | private final AtomicReference<ReversableArray> eTimeBuffer = new AtomicReference<ReversableArray>( |
| | | new ReversableArray(100000)); |
| | | |
| | | private final ConsoleApplication app; |
| | | |
| | | private DataSource[] dataSourcePrototypes; |
| | | |
| | | // Thread local copies of the data sources |
| | | private final ThreadLocal<DataSource[]> dataSources = |
| | | new ThreadLocal<DataSource[]>() |
| | | private final ThreadLocal<DataSource[]> dataSources = new ThreadLocal<DataSource[]>() |
| | | { |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | protected DataSource[] initialValue() |
| | | { |
| | | final DataSource[] prototypes = getDataSources(); |
| | |
| | | |
| | | private volatile boolean stopRequested; |
| | | |
| | | private int numThreads; |
| | | private int numConcurrentTasks; |
| | | |
| | | private int numConnections; |
| | | |
| | |
| | | |
| | | private int statsInterval; |
| | | |
| | | private final IntegerArgument numThreadsArgument; |
| | | private double targetTimeInMS; |
| | | |
| | | private final IntegerArgument numConcurrentTasksArgument; |
| | | |
| | | private final IntegerArgument maxIterationsArgument; |
| | | |
| | |
| | | |
| | | |
| | | PerformanceRunner(final ArgumentParser argParser, |
| | | final ConsoleApplication app, |
| | | boolean neverRebind, boolean neverAsynchronous, |
| | | boolean alwaysSingleThreaded) |
| | | final ConsoleApplication app, final boolean neverRebind, |
| | | final boolean neverAsynchronous, final boolean alwaysSingleThreaded) |
| | | throws ArgumentException |
| | | { |
| | | this.app = app; |
| | | numThreadsArgument = new IntegerArgument("numThreads", 't', "numThreads", |
| | | false, false, true, LocalizableMessage.raw("{numThreads}"), 1, null, |
| | | true, 1, false, 0, LocalizableMessage |
| | | .raw("Number of worker threads per connection")); |
| | | numThreadsArgument.setPropertyName("numThreads"); |
| | | if(!alwaysSingleThreaded) |
| | | numConcurrentTasksArgument = new IntegerArgument("numConcurrentTasks", 't', |
| | | "numConcurrentTasks", false, false, true, |
| | | LocalizableMessage.raw("{numConcurrentTasks}"), 1, null, true, 1, |
| | | false, 0, |
| | | LocalizableMessage.raw("Number of concurrent tasks per connection")); |
| | | numConcurrentTasksArgument.setPropertyName("numConcurrentTasks"); |
| | | if (!alwaysSingleThreaded) |
| | | { |
| | | argParser.addArgument(numThreadsArgument); |
| | | argParser.addArgument(numConcurrentTasksArgument); |
| | | } |
| | | else |
| | | { |
| | | numThreadsArgument.addValue("1"); |
| | | numConcurrentTasksArgument.addValue("1"); |
| | | } |
| | | |
| | | numConnectionsArgument = new IntegerArgument("numConnections", 'c', |
| | | "numConnections", false, false, true, LocalizableMessage |
| | | .raw("{numConnections}"), 1, null, true, 1, false, 0, |
| | | "numConnections", false, false, true, |
| | | LocalizableMessage.raw("{numConnections}"), 1, null, true, 1, false, 0, |
| | | LocalizableMessage.raw("Number of connections")); |
| | | numConnectionsArgument.setPropertyName("numConnections"); |
| | | argParser.addArgument(numConnectionsArgument); |
| | | |
| | | maxIterationsArgument = new IntegerArgument("maxIterations", 'm', |
| | | "maxIterations", false, false, true, LocalizableMessage |
| | | .raw("{maxIterations}"), 0, null, LocalizableMessage |
| | | .raw("Max iterations, 0 for unlimited")); |
| | | "maxIterations", false, false, true, |
| | | LocalizableMessage.raw("{maxIterations}"), 0, null, |
| | | LocalizableMessage.raw("Max iterations, 0 for unlimited")); |
| | | maxIterationsArgument.setPropertyName("maxIterations"); |
| | | argParser.addArgument(maxIterationsArgument); |
| | | |
| | | statsIntervalArgument = new IntegerArgument("statInterval", 'i', |
| | | "statInterval", false, false, true, LocalizableMessage |
| | | .raw("{statInterval}"), 5, null, true, 1, false, 0, |
| | | "statInterval", false, false, true, |
| | | LocalizableMessage.raw("{statInterval}"), 5, null, true, 1, false, 0, |
| | | LocalizableMessage |
| | | .raw("Display results each specified number of seconds")); |
| | | statsIntervalArgument.setPropertyName("statInterval"); |
| | | argParser.addArgument(statsIntervalArgument); |
| | | |
| | | targetThroughputArgument = new IntegerArgument("targetThroughput", 'M', |
| | | "targetThroughput", false, false, true, LocalizableMessage |
| | | .raw("{targetThroughput}"), 0, null, LocalizableMessage |
| | | .raw("Target average throughput to achieve")); |
| | | "targetThroughput", false, false, true, |
| | | LocalizableMessage.raw("{targetThroughput}"), 0, null, |
| | | LocalizableMessage.raw("Target average throughput to achieve")); |
| | | targetThroughputArgument.setPropertyName("targetThroughput"); |
| | | argParser.addArgument(targetThroughputArgument); |
| | | |
| | |
| | | noRebindArgument = new BooleanArgument("noRebind", 'F', "noRebind", |
| | | LocalizableMessage.raw("Keep connections open and don't rebind")); |
| | | noRebindArgument.setPropertyName("noRebind"); |
| | | if(!neverRebind) |
| | | if (!neverRebind) |
| | | { |
| | | argParser.addArgument(noRebindArgument); |
| | | } |
| | |
| | | } |
| | | |
| | | asyncArgument = new BooleanArgument("asynchronous", 'A', "asynchronous", |
| | | LocalizableMessage.raw("Use asynchronous mode and don't " + |
| | | "wait for results before sending the next request")); |
| | | LocalizableMessage.raw("Use asynchronous mode and don't " |
| | | + "wait for results before sending the next request")); |
| | | asyncArgument.setPropertyName("asynchronous"); |
| | | if(!neverAsynchronous) |
| | | if (!neverAsynchronous) |
| | | { |
| | | argParser.addArgument(asyncArgument); |
| | | } |
| | | |
| | | arguments = new StringArgument("argument", 'g', "argument", false, true, |
| | | true, LocalizableMessage.raw("{generator function or static string}"), |
| | | null, null, |
| | | LocalizableMessage.raw("Argument used to evaluate the Java " + |
| | | "style format strings in program parameters (ie. Base DN, " + |
| | | "Search Filter). The set of all arguments provided form the " + |
| | | "the argument list in order. Besides static string " + |
| | | "arguments, they can be generated per iteration with the " + |
| | | "following functions: " + StaticUtils.EOL + |
| | | DataSource.getUsage())); |
| | | arguments = new StringArgument( |
| | | "argument", |
| | | 'g', |
| | | "argument", |
| | | false, |
| | | true, |
| | | true, |
| | | LocalizableMessage.raw("{generator function or static string}"), |
| | | null, |
| | | null, |
| | | LocalizableMessage.raw("Argument used to evaluate the Java " |
| | | + "style format strings in program parameters (ie. Base DN, " |
| | | + "Search Filter). The set of all arguments provided form the " |
| | | + "the argument list in order. Besides static string " |
| | | + "arguments, they can be generated per iteration with the " |
| | | + "following functions: " + StaticUtils.EOL + DataSource.getUsage())); |
| | | argParser.addArgument(arguments); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public void handleUnsolicitedNotification( |
| | | final ExtendedResult notification) |
| | | public void handleUnsolicitedNotification(final ExtendedResult notification) |
| | | { |
| | | // Ignore |
| | | } |
| | |
| | | public final void validate() throws ArgumentException |
| | | { |
| | | numConnections = numConnectionsArgument.getIntValue(); |
| | | numThreads = numThreadsArgument.getIntValue(); |
| | | maxIterations = maxIterationsArgument.getIntValue() / |
| | | numConnections / numThreads; |
| | | numConcurrentTasks = numConcurrentTasksArgument.getIntValue(); |
| | | maxIterations = maxIterationsArgument.getIntValue() / numConnections; |
| | | statsInterval = statsIntervalArgument.getIntValue() * 1000; |
| | | targetThroughput = targetThroughputArgument.getIntValue(); |
| | | |
| | | isAsync = asyncArgument.isPresent(); |
| | | noRebind = noRebindArgument.isPresent(); |
| | | |
| | | if (!noRebindArgument.isPresent() && this.numThreads > 1) |
| | | if (!noRebindArgument.isPresent() && this.numConcurrentTasks > 1) |
| | | { |
| | | throw new ArgumentException(LocalizableMessage.raw("--" |
| | | + noRebindArgument.getLongIdentifier() + " must be used if --" |
| | | + numThreadsArgument.getLongIdentifier() + " is > 1")); |
| | | + numConcurrentTasksArgument.getLongIdentifier() + " is > 1")); |
| | | } |
| | | |
| | | if (!noRebindArgument.isPresent() && asyncArgument.isPresent()) |
| | |
| | | } |
| | | |
| | | dataSourcePrototypes = DataSource.parse(arguments.getValues()); |
| | | |
| | | targetTimeInMS = |
| | | (1.0 / (targetThroughput / (double) (numConcurrentTasks * numConnections))) * 1000.0; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | abstract ConnectionWorker newConnectionWorker( |
| | | final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory); |
| | | |
| | | |
| | | |
| | | abstract StatsThread newStatsThread(); |
| | | |
| | | |
| | | |
| | | abstract WorkerThread newWorkerThread(AsynchronousConnection connection, |
| | | ConnectionFactory connectionFactory); |
| | | |
| | | |
| | | |
| | | final int run(final ConnectionFactory connectionFactory) |
| | | { |
| | | final List<Thread> threads = new ArrayList<Thread>(); |
| | | final List<ConnectionWorker> workers = new ArrayList<ConnectionWorker>(); |
| | | final List<AsynchronousConnection> connections = new ArrayList<AsynchronousConnection>(); |
| | | |
| | | AsynchronousConnection connection = null; |
| | | Thread thread; |
| | | try |
| | | { |
| | | for (int i = 0; i < numConnections; i++) |
| | |
| | | connection.addConnectionEventListener(this); |
| | | connections.add(connection); |
| | | } |
| | | for (int j = 0; j < numThreads; j++) |
| | | { |
| | | thread = newWorkerThread(connection, connectionFactory); |
| | | |
| | | threads.add(thread); |
| | | thread.start(); |
| | | } |
| | | final ConnectionWorker worker = newConnectionWorker(connection, |
| | | connectionFactory); |
| | | workers.add(worker); |
| | | worker.startWork(); |
| | | } |
| | | |
| | | final Thread statsThread = newStatsThread(); |
| | | statsThread.start(); |
| | | |
| | | for (final Thread t : threads) |
| | | for (final ConnectionWorker w : workers) |
| | | { |
| | | t.join(); |
| | | w.waitFor(); |
| | | } |
| | | stopRequested = true; |
| | | statsThread.join(); |
| | |
| | | private final class SearchStatsHandler extends |
| | | UpdateStatsResultHandler<Result> implements SearchResultHandler |
| | | { |
| | | private SearchStatsHandler(final long startTime) |
| | | private SearchStatsHandler(final long startTime, |
| | | final AsynchronousConnection connection, final ConnectionWorker worker) |
| | | { |
| | | super(startTime); |
| | | super(startTime, connection, worker); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleEntry(final SearchResultEntry entry) |
| | | { |
| | | entryRecentCount.getAndIncrement(); |
| | |
| | | |
| | | |
| | | |
| | | @Override |
| | | public boolean handleReference(final SearchResultReference reference) |
| | | { |
| | | return true; |
| | |
| | | |
| | | |
| | | |
| | | private final class SearchWorkerThread extends WorkerThread |
| | | private final class SearchWorkerThread extends ConnectionWorker |
| | | { |
| | | private SearchRequest sr; |
| | | |
| | |
| | | sr.setFilter(String.format(filter, data)); |
| | | sr.setName(String.format(baseDN, data)); |
| | | } |
| | | return connection.search(sr, new SearchStatsHandler(startTime)); |
| | | return connection.search(sr, new SearchStatsHandler(startTime, |
| | | connection, this)); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | @Override |
| | | StatsThread newStatsThread() |
| | | ConnectionWorker newConnectionWorker( |
| | | final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | { |
| | | return new SearchStatsThread(); |
| | | return new SearchWorkerThread(connection, connectionFactory); |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | WorkerThread newWorkerThread(final AsynchronousConnection connection, |
| | | final ConnectionFactory connectionFactory) |
| | | StatsThread newStatsThread() |
| | | { |
| | | return new SearchWorkerThread(connection, connectionFactory); |
| | | return new SearchStatsThread(); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | // Create the command-line argument parser for use with this |
| | | // program. |
| | | final LocalizableMessage toolDescription = |
| | | INFO_SEARCHRATE_TOOL_DESCRIPTION.get(); |
| | | final ArgumentParser argParser = new ArgumentParser(SearchRate.class |
| | | .getName(), toolDescription, false, true, 1, 0, |
| | | final LocalizableMessage toolDescription = INFO_SEARCHRATE_TOOL_DESCRIPTION |
| | | .get(); |
| | | final ArgumentParser argParser = new ArgumentParser( |
| | | SearchRate.class.getName(), toolDescription, false, true, 1, 0, |
| | | "[filter format string] [attributes ...]"); |
| | | |
| | | ConnectionFactoryProvider connectionFactoryProvider; |
| | |
| | | try |
| | | { |
| | | TransportFactory.setInstance(new PerfToolTCPNIOTransportFactory()); |
| | | connectionFactoryProvider = |
| | | new ConnectionFactoryProvider(argParser, this); |
| | | connectionFactoryProvider = new ConnectionFactoryProvider(argParser, this); |
| | | runner = new SearchPerformanceRunner(argParser, this); |
| | | |
| | | propertiesFileArgument = new StringArgument("propertiesFilePath", null, |
| | |
| | | |
| | | searchScope = new MultiChoiceArgument<SearchScope>("searchScope", 's', |
| | | "searchScope", false, true, INFO_SEARCH_SCOPE_PLACEHOLDER.get(), |
| | | SearchScope.values(), false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE |
| | | .get()); |
| | | SearchScope.values(), false, |
| | | INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get()); |
| | | searchScope.setPropertyName("searchScope"); |
| | | searchScope.setDefaultValue(SearchScope.WHOLE_SUBTREE); |
| | | argParser.addArgument(searchScope); |
| | | |
| | | dereferencePolicy = new MultiChoiceArgument<DereferenceAliasesPolicy>( |
| | | "derefpolicy", 'a', "dereferencePolicy", false, true, |
| | | INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), DereferenceAliasesPolicy |
| | | .values(), false, INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY |
| | | .get()); |
| | | INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), |
| | | DereferenceAliasesPolicy.values(), false, |
| | | INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get()); |
| | | dereferencePolicy.setPropertyName("dereferencePolicy"); |
| | | dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER); |
| | | argParser.addArgument(dereferencePolicy); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | connectionFactory = |
| | | connectionFactoryProvider.getAuthenticatedConnectionFactory(); |
| | | connectionFactory = connectionFactoryProvider |
| | | .getAuthenticatedConnectionFactory(); |
| | | runner.validate(); |
| | | } |
| | | catch (final ArgumentException ae) |
| | |
| | | import static com.sun.opends.sdk.messages.Messages.*; |
| | | import static com.sun.opends.sdk.util.StaticUtils.*; |
| | | |
| | | import java.util.Comparator; |
| | | |
| | | import org.opends.sdk.schema.*; |
| | | |
| | | import com.sun.opends.sdk.util.StaticUtils; |
| | |
| | | } |
| | | catch (final UnknownSchemaElementException e) |
| | | { |
| | | final LocalizableMessage message = ERR_RDN_TYPE_NOT_FOUND.get(ava, e |
| | | .getMessageObject()); |
| | | final LocalizableMessage message = ERR_RDN_TYPE_NOT_FOUND.get(ava, |
| | | e.getMessageObject()); |
| | | throw new LocalizedIllegalArgumentException(message); |
| | | } |
| | | } |
| | |
| | | char c; |
| | | if ((c = reader.read()) != '=') |
| | | { |
| | | final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_NO_EQUAL.get(reader |
| | | .getString(), attribute.getNameOrOID(), c); |
| | | final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_NO_EQUAL.get( |
| | | reader.getString(), attribute.getNameOrOID(), c); |
| | | throw new LocalizedIllegalArgumentException(message); |
| | | } |
| | | |
| | |
| | | |
| | | private final ByteString attributeValue; |
| | | |
| | | // Cached normalized value using equality matching rule. |
| | | private ByteString equalityNormalizedAttributeValue = null; |
| | | |
| | | // Cached normalized value using ordering matching rule. |
| | | private ByteString orderingNormalizedAttributeValue = null; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | * @param attributeValue |
| | | * The attribute value. |
| | | * @throws NullPointerException |
| | | * If {@code attributeType} or {@code attributeValue} was {@code |
| | | * null}. |
| | | * If {@code attributeType} or {@code attributeValue} was |
| | | * {@code null}. |
| | | */ |
| | | public AVA(final AttributeType attributeType, final ByteString attributeValue) |
| | | throws NullPointerException |
| | |
| | | * @throws UnknownSchemaElementException |
| | | * If {@code attributeType} was not found in the default schema. |
| | | * @throws NullPointerException |
| | | * If {@code attributeType} or {@code attributeValue} was {@code |
| | | * null}. |
| | | * If {@code attributeType} or {@code attributeValue} was |
| | | * {@code null}. |
| | | */ |
| | | public AVA(final String attributeType, final Object attributeValue) |
| | | throws UnknownSchemaElementException, NullPointerException |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public int compareTo(final AVA ava) |
| | | { |
| | | int result = attributeType.compareTo(ava.attributeType); |
| | | final int result = attributeType.compareTo(ava.attributeType); |
| | | if (result != 0) |
| | | { |
| | | return result > 0 ? 1 : -1; |
| | | } |
| | | final ByteString normalizedValue = getNormalizeValue(); |
| | | |
| | | final ByteString normalizedValue = getOrderingNormalizedValue(); |
| | | final ByteString otherNormalizedValue = ava.getOrderingNormalizedValue(); |
| | | final MatchingRule rule = attributeType.getOrderingMatchingRule(); |
| | | try |
| | | if (rule != null) |
| | | { |
| | | if (rule != null) |
| | | { |
| | | // Check equality assertion first. |
| | | final Assertion lteAssertion = rule |
| | | .getLessOrEqualAssertion(ava.attributeValue); |
| | | final ConditionResult lteResult = lteAssertion.matches(normalizedValue); |
| | | final Assertion gteAssertion = rule |
| | | .getGreaterOrEqualAssertion(ava.attributeValue); |
| | | final ConditionResult gteResult = gteAssertion.matches(normalizedValue); |
| | | |
| | | if (lteResult.equals(gteResult)) |
| | | { |
| | | // it is equal to the assertion value. |
| | | return 0; |
| | | } |
| | | else if (lteResult == ConditionResult.TRUE) |
| | | { |
| | | return -1; |
| | | } |
| | | else |
| | | { |
| | | return 1; |
| | | } |
| | | } |
| | | final Comparator<ByteSequence> comparator = rule.comparator(); |
| | | return comparator.compare(normalizedValue, otherNormalizedValue); |
| | | } |
| | | catch (final DecodeException de) |
| | | else |
| | | { |
| | | // use the bytestring comparison as default. |
| | | return normalizedValue.compareTo(otherNormalizedValue); |
| | | } |
| | | |
| | | if (result == 0) |
| | | { |
| | | final ByteString nv1 = normalizedValue; |
| | | final ByteString nv2 = ava.getNormalizeValue(); |
| | | result = nv1.compareTo(nv2); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | else if (obj instanceof AVA) |
| | | { |
| | | return compareTo((AVA) obj) == 0; |
| | | final AVA ava = (AVA) obj; |
| | | |
| | | if (!attributeType.equals(ava.attributeType)) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | final ByteString normalizedValue = getEqualityNormalizedValue(); |
| | | final ByteString otherNormalizedValue = ava.getEqualityNormalizedValue(); |
| | | final MatchingRule rule = attributeType.getEqualityMatchingRule(); |
| | | if (rule != null) |
| | | { |
| | | final Comparator<ByteSequence> comparator = rule.comparator(); |
| | | return comparator.compare(normalizedValue, otherNormalizedValue) != 0 ? false |
| | | : true; |
| | | } |
| | | else |
| | | { |
| | | return normalizedValue.equals(otherNormalizedValue); |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | @Override |
| | | public int hashCode() |
| | | { |
| | | return attributeType.hashCode() * 31 + getNormalizeValue().hashCode(); |
| | | return attributeType.hashCode() * 31 |
| | | + getEqualityNormalizedValue().hashCode(); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | private ByteString getNormalizeValue() |
| | | { |
| | | final MatchingRule matchingRule = attributeType.getEqualityMatchingRule(); |
| | | if (matchingRule != null) |
| | | { |
| | | try |
| | | { |
| | | return matchingRule.normalizeAttributeValue(attributeValue); |
| | | } |
| | | catch (final DecodeException de) |
| | | { |
| | | // Ignore - we'll drop back to the user provided value. |
| | | } |
| | | } |
| | | return attributeValue; |
| | | } |
| | | |
| | | |
| | | |
| | | StringBuilder toString(final StringBuilder builder) |
| | | { |
| | | if (!attributeType.getNames().iterator().hasNext()) |
| | |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | |
| | | |
| | | private ByteString getEqualityNormalizedValue() |
| | | { |
| | | final ByteString normalizedValue = equalityNormalizedAttributeValue; |
| | | |
| | | if (normalizedValue != null) |
| | | { |
| | | return normalizedValue; |
| | | } |
| | | |
| | | final MatchingRule matchingRule = attributeType.getEqualityMatchingRule(); |
| | | if (matchingRule != null) |
| | | { |
| | | try |
| | | { |
| | | equalityNormalizedAttributeValue = matchingRule |
| | | .normalizeAttributeValue(attributeValue); |
| | | } |
| | | catch (final DecodeException de) |
| | | { |
| | | // Unable to normalize, so default to byte-wise comparison. |
| | | equalityNormalizedAttributeValue = attributeValue; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // No matching rule, so default to byte-wise comparison. |
| | | equalityNormalizedAttributeValue = attributeValue; |
| | | } |
| | | |
| | | return equalityNormalizedAttributeValue; |
| | | } |
| | | |
| | | |
| | | |
| | | private ByteString getOrderingNormalizedValue() |
| | | { |
| | | final ByteString normalizedValue = orderingNormalizedAttributeValue; |
| | | |
| | | if (normalizedValue != null) |
| | | { |
| | | return normalizedValue; |
| | | } |
| | | |
| | | final MatchingRule matchingRule = attributeType.getEqualityMatchingRule(); |
| | | if (matchingRule != null) |
| | | { |
| | | try |
| | | { |
| | | orderingNormalizedAttributeValue = matchingRule |
| | | .normalizeAttributeValue(attributeValue); |
| | | } |
| | | catch (final DecodeException de) |
| | | { |
| | | // Unable to normalize, so default to equality matching. |
| | | orderingNormalizedAttributeValue = getEqualityNormalizedValue(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // No matching rule, so default to equality matching. |
| | | orderingNormalizedAttributeValue = getEqualityNormalizedValue(); |
| | | } |
| | | |
| | | return orderingNormalizedAttributeValue; |
| | | } |
| | | } |
| | |
| | | import org.opends.sdk.asn1.ASN1Reader; |
| | | import org.opends.sdk.asn1.ASN1ReaderTestCase; |
| | | |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.glassfish.grizzly.memory.ByteBufferWrapper; |
| | | |
| | | |
| | |
| | | throws IOException |
| | | { |
| | | final ByteBufferWrapper buffer = new ByteBufferWrapper(ByteBuffer.wrap(b)); |
| | | final ASN1BufferReader reader = new ASN1BufferReader(maxElementSize); |
| | | final ASN1BufferReader reader = new ASN1BufferReader(maxElementSize, |
| | | TransportFactory.getInstance().getDefaultMemoryManager()); |
| | | reader.appendBytesRead(buffer); |
| | | return reader; |
| | | } |
| | |
| | | import org.opends.sdk.asn1.ASN1WriterTestCase; |
| | | |
| | | import org.glassfish.grizzly.Buffer; |
| | | import org.glassfish.grizzly.TransportFactory; |
| | | import org.glassfish.grizzly.memory.ByteBufferWrapper; |
| | | |
| | | |
| | |
| | | throws DecodeException, IOException |
| | | { |
| | | final ByteBufferWrapper buffer = new ByteBufferWrapper(ByteBuffer.wrap(encodedBytes)); |
| | | final ASN1BufferReader reader = new ASN1BufferReader(0); |
| | | final ASN1BufferReader reader = new ASN1BufferReader(0, TransportFactory |
| | | .getInstance().getDefaultMemoryManager()); |
| | | reader.appendBytesRead(buffer); |
| | | return reader; |
| | | } |