Bug 54584 - MongoDB plugin

Bugzilla Id: 54584

git-svn-id: https://svn.apache.org/repos/asf/jmeter/trunk@1451961 13f79535-47bb-0310-9956-ffa450edef68

Former-commit-id: f40c2e8e5d
This commit is contained in:
Philippe Mouawad 2013-03-02 23:45:21 +00:00
parent 5e8ba0f025
commit b0365ef0a7
18 changed files with 1101 additions and 1 deletions

View File

@ -213,6 +213,11 @@ logkit.jar = logkit-${logkit.version}.jar
logkit.loc = ${maven2.repo}/logkit/logkit/${logkit.version}
logkit.md5 = 8D82A3E91AAE216D0A2A40B837A232FF
mongo-java-driver.version = 2.10.1
mongo-java-driver.jar = mongo-java-driver-${mongo-java-driver.version}.jar
mongo-java-driver.loc = ${maven2.repo}/org/mongodb/mongo-java-driver/${mongo-java-driver.version}
mongo-java-driver.md5 = e12feedcdd249b3973e24d03f6cb5131
slf4j-api.version = 1.7.2
slf4j-api.jar = slf4j-api-${slf4j-api.version}.jar
slf4j-api.loc = ${maven2.repo}/org/slf4j/slf4j-api/${slf4j-api.version}

View File

@ -141,6 +141,7 @@
<class location="${dest.jar}/ApacheJMeter_mail.jar"/>
<class location="${dest.jar}/ApacheJMeter_monitors.jar"/>
<class location="${dest.jar}/ApacheJMeter_native.jar"/>
<class location="${dest.jar}/ApacheJMeter_mongodb.jar"/>
<class location="${dest.jar}/ApacheJMeter_report.jar"/>
<class location="${dest.jar}/ApacheJMeter_tcp.jar"/>
<class location="${dest.jar.jmeter}/ApacheJMeter.jar" />
@ -148,6 +149,7 @@
<sourcePath path="${src.tcp}" />
<sourcePath path="${src.jms}" />
<sourcePath path="${src.native}" />
<sourcePath path="${src.mongodb}" />
<sourcePath path="${src.report}" />
<auxClasspath>
@ -211,6 +213,7 @@
<property name="src.monitor.model" value="src/monitor/model"/>
<property name="src.jms" value="src/protocol/jms"/>
<property name="src.native" value="src/protocol/native"/>
<property name="src.mongodb" value="src/protocol/mongodb"/>
<property name="src.report" value="src/reports"/>
<!-- Where the documentation sources live -->
@ -260,6 +263,7 @@
<property name="build.monitor.model" value="build/monitor/model"/>
<property name="build.jms" value="build/protocol/jms"/>
<property name="build.native" value="build/protocol/native"/>
<property name="build.mongodb" value="build/protocol/mongodb"/>
<property name="build.report" value="build/reports"/>
<property name="build.test" value="build/test"/>
<property name="build.res" value="build/res"/>
@ -448,6 +452,7 @@
<pathelement location="${lib.dir}/${jsoup.jar}"/>
<pathelement location="${lib.dir}/${junit.jar}"/>
<pathelement location="${lib.dir}/${logkit.jar}"/>
<pathelement location="${lib.dir}/${mongo-java-driver.jar}"/>
<pathelement location="${lib.dir}/${serializer.jar}"/>
<pathelement location="${lib.dir}/${slf4j-api.jar}"/>
<pathelement location="${lib.dir}/${soap.jar}"/>
@ -839,9 +844,23 @@
</classpath>
</javac>
</target>
<target name="compile-mongodb" depends="compile-jorphan,compile-core,compile-components"
description="Compile components specific to MongoDB sampling.">
<mkdir dir="${build.mongodb}"/>
<javac srcdir="${src.mongodb}" destdir="${build.mongodb}" source="${src.java.version}" optimize="${optimize}" debug="on" target="${target.java.version}"
includeAntRuntime="${includeAntRuntime}" deprecation="${deprecation}" encoding="${encoding}">
<include name="**/*.java"/>
<classpath>
<pathelement location="${build.jorphan}"/>
<pathelement location="${build.core}"/>
<path refid="classpath"/>
</classpath>
</javac>
</target>
<target name="compile"
depends="_message_3rdParty,compile-core,compile-components,compile-functions,compile-protocols,compile-rmi,compile-monitor,compile-junit,compile-jms,compile-native, compile-report"
depends="_message_3rdParty,compile-core,compile-components,compile-functions,compile-protocols,compile-rmi,compile-monitor,compile-junit,compile-jms,compile-native, compile-mongodb, compile-report"
description="Compile everything."/>
<target name="run_gui" depends="package" description="Run the JMeter GUI off the jar files">
@ -1117,6 +1136,18 @@ run JMeter unless all the JMeter jars are added.
<fileset dir="${src.native}" includes="**/*.properties" />
</jar>
<!-- mongodb -->
<!-- Ensure that build dir exists, even if MongoDB has not been built -->
<mkdir dir="${build.mongodb}"/>
<jar jarfile="${dest.jar}/ApacheJMeter_mongodb.jar" manifest="${build.dir}/MANIFEST_BIN.MF">
<zipfileset file="${resources.meta-inf}/default.notice"
fullpath="META-INF/NOTICE" />
<zipfileset file="${resources.meta-inf}/default.license"
fullpath="META-INF/LICENSE" />
<fileset dir="${build.mongodb}" includes="**/*.class" />
<fileset dir="${src.mongodb}" includes="**/*.properties" />
</jar>
<jar jarfile="${lib.dir}/jorphan.jar" manifest="${build.dir}/MANIFEST_BIN.MF">
<zipfileset file="${resources.meta-inf}/default.notice"
fullpath="META-INF/NOTICE" />
@ -2728,6 +2759,7 @@ run JMeter unless all the JMeter jars are added.
<process_jarfile jarname="jsoup"/>
<process_jarfile jarname="junit"/>
<process_jarfile jarname="logkit"/>
<process_jarfile jarname="mongo-java-driver"/>
<process_jarfile jarname="serializer"/>
<process_jarfile jarname="slf4j-api"/>
<process_jarfile jarname="soap"/>

View File

@ -0,0 +1,49 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_parent</artifactId>
<version>@MAVEN.DEPLOY.VERSION@</version>
<relativePath>.</relativePath>
</parent>
<artifactId>ApacheJMeter_mongodb</artifactId>
<name>Apache JMeter MongoDB</name>
<dependencies>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>jorphan</artifactId>
<version>@MAVEN.DEPLOY.VERSION@</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_core</artifactId>
<version>@MAVEN.DEPLOY.VERSION@</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_components</artifactId>
<version>@MAVEN.DEPLOY.VERSION@</version>
</dependency>
</dependencies>
</project>

View File

@ -82,6 +82,7 @@ under the License.
<js_rhino.version>1.7R4</js_rhino.version>
<junit.version>4.10</junit.version>
<logkit.version>2.0</logkit.version>
<mongo-java-driver.version>2.10.1</mongo-java-driver.version>
<slf4j.version>1.7.2</slf4j.version>
<soap.version>2.3.1</soap.version>
<tidy.version>r938</tidy.version>
@ -344,6 +345,11 @@ under the License.
<artifactId>jodd-lagarto</artifactId>
<version>${jodd.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo-java-driver.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>

View File

@ -0,0 +1,264 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.config;
import org.apache.jmeter.config.ConfigElement;
import org.apache.jmeter.protocol.mongodb.mongo.MongoDB;
import org.apache.jmeter.protocol.mongodb.mongo.MongoUtils;
import org.apache.jmeter.testbeans.TestBean;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import com.mongodb.MongoOptions;
/**
*/
public class MongoSourceElement
extends AbstractTestElement
implements ConfigElement, TestStateListener, TestBean {
private static final Logger log = LoggingManager.getLoggerForClass();
public final static String CONNECTION = "MongoSourceElement.connection"; //$NON-NLS-1$
public final static String SOURCE = "MongoSourceElement.source"; //$NON-NLS-1$
public final static String AUTO_CONNECT_RETRY = "MongoSourceElement.autoConnectRetry"; //$NON-NLS-1$
public final static String CONNECTIONS_PER_HOST = "MongoSourceElement.connectionsPerHost"; //$NON-NLS-1$
public final static String CONNECT_TIMEOUT = "MongoSourceElement.connectTimeout"; //$NON-NLS-1$
public final static String MAX_AUTO_CONNECT_RETRY_TIME = "MongoSourceElement.maxAutoConnectRetryTime"; //$NON-NLS-1$
public final static String MAX_WAIT_TIME = "MongoSourceElement.maxWaitTime"; //$NON-NLS-1$
public final static String SOCKET_TIMEOUT = "MongoSourceElement.socketTimeout"; //$NON-NLS-1$
public final static String SOCKET_KEEP_ALIVE = "MongoSourceElement.socketKeepAlive"; //$NON-NLS-1$
public final static String THREADS_ALLOWED_TO_BLOCK_MULTIPLIER = "MongoSourceElement.threadsAllowedToBlockForConnectionMultiplier"; //$NON-NLS-1$
public final static String FSYNC = "MongoSourceElement.fsync"; //$NON-NLS-1$
public final static String SAFE = "MongoSourceElement.safe"; //$NON-NLS-1$
public final static String WAIT_FOR_JOURNALING = "MongoSourceElement.waitForJournaling"; //$NON-NLS-1$
public final static String WRITE_OPERATION_NUMBER_OF_SERVERS = "MongoSourceElement.writeOperationNumberOfServers"; //$NON-NLS-1$
public final static String WRITE_OPERATION_TIMEOUT = "MongoSourceElement.writeOperationTimeout"; //$NON-NLS-1$
public String getTitle() {
return this.getName();
}
public String getConnection() {
return getPropertyAsString(CONNECTION);
}
public void setConnection(String connection) {
setProperty(CONNECTION, connection);
}
public String getSource() {
return getPropertyAsString(SOURCE);
}
public void setSource(String source) {
setProperty(SOURCE, source);
}
public String getAutoConnectRetry() {
return getPropertyAsString(AUTO_CONNECT_RETRY);
}
public void setAutoConnectRetry(String autoConnectRetry) {
setProperty(AUTO_CONNECT_RETRY, autoConnectRetry);
}
public String getConnectionsPerHost() {
return getPropertyAsString(CONNECTIONS_PER_HOST);
}
public void setConnectionsPerHost(String connectionsPerHost) {
setProperty(CONNECTIONS_PER_HOST, connectionsPerHost);
}
public String getConnectTimeout() {
return getPropertyAsString(CONNECT_TIMEOUT);
}
public void setConnectTimeout(String connectTimeout) {
setProperty(CONNECT_TIMEOUT, connectTimeout);
}
public String getMaxAutoConnectRetryTime() {
return getPropertyAsString(MAX_AUTO_CONNECT_RETRY_TIME);
}
public void setMaxAutoConnectRetryTime(String maxAutoConnectRetryTime) {
setProperty(MAX_AUTO_CONNECT_RETRY_TIME, maxAutoConnectRetryTime);
}
public String getMaxWaitTime() {
return getPropertyAsString(MAX_WAIT_TIME);
}
public void setMaxWaitTime(String maxWaitTime) {
setProperty(MAX_WAIT_TIME, maxWaitTime);
}
public String getSocketTimeout() {
return getPropertyAsString(SOCKET_TIMEOUT);
}
public void setSocketTimeout(String socketTimeout) {
setProperty(SOCKET_TIMEOUT, socketTimeout);
}
public String getSocketKeepAlive() {
return getPropertyAsString(SOCKET_KEEP_ALIVE);
}
public void setSocketKeepAlive(String socketKeepAlive) {
setProperty(SOCKET_KEEP_ALIVE, socketKeepAlive);
}
public String getThreadsAllowedToBlockForConnectionMultiplier() {
return getPropertyAsString(THREADS_ALLOWED_TO_BLOCK_MULTIPLIER);
}
public void setThreadsAllowedToBlockForConnectionMultiplier(String threadsAllowed) {
setProperty(THREADS_ALLOWED_TO_BLOCK_MULTIPLIER, threadsAllowed);
}
public String getFsync() {
return getPropertyAsString(FSYNC);
}
public void setFsync(String fsync) {
setProperty(FSYNC, fsync);
}
public String getSafe() {
return getPropertyAsString(SAFE);
}
public void setSafe(String safe) {
setProperty(SAFE, safe);
}
public String getWaitForJournaling() {
return getPropertyAsString(WAIT_FOR_JOURNALING);
}
public void setWaitForJournaling(String waitForJournaling) {
setProperty(WAIT_FOR_JOURNALING, waitForJournaling);
}
public String getWriteOperationNumberOfServers() {
return getPropertyAsString(WRITE_OPERATION_NUMBER_OF_SERVERS);
}
public void setWriteOperationNumberOfServers(String writeOperationNumberOfServers) {
setProperty(WRITE_OPERATION_NUMBER_OF_SERVERS, writeOperationNumberOfServers);
}
public String getWriteOperationTimeout() {
return getPropertyAsString(WRITE_OPERATION_TIMEOUT);
}
public void setWriteOperationTimeout(String writeOperationTimeout) {
setProperty(WRITE_OPERATION_TIMEOUT, writeOperationTimeout);
}
public static MongoDB getMongoDB(String source) {
Object mongoSource = JMeterContextService.getContext().getVariables().getObject(source);
if(mongoSource == null) {
throw new IllegalStateException("mongoSource is null");
}
else {
if(mongoSource instanceof MongoDB) {
return (MongoDB)mongoSource;
}
else {
throw new IllegalStateException("Variable:"+ source +" is not a MongoDB instance, class:"+(mongoSource != null ? mongoSource.getClass():"null"));
}
}
}
@Override
public void addConfigElement(ConfigElement configElement) {
}
@Override
public boolean expectsModification() {
return false;
}
@Override
public void testStarted() {
if(log.isDebugEnabled()) {
log.debug(getTitle() + " testStarted");
}
MongoOptions mongoOptions = new MongoOptions();
mongoOptions.autoConnectRetry = Boolean.parseBoolean(getAutoConnectRetry());
mongoOptions.connectTimeout = Integer.parseInt(getConnectTimeout());
mongoOptions.connectionsPerHost = Integer.parseInt(getConnectionsPerHost());
mongoOptions.fsync = Boolean.parseBoolean(getFsync());
mongoOptions.j = Boolean.parseBoolean(getWaitForJournaling());
mongoOptions.maxAutoConnectRetryTime = Integer.parseInt(getMaxAutoConnectRetryTime());
mongoOptions.maxWaitTime = Integer.parseInt(getMaxWaitTime());
mongoOptions.safe = Boolean.parseBoolean(getSafe());
mongoOptions.socketKeepAlive = Boolean.parseBoolean(getSocketKeepAlive());
mongoOptions.socketTimeout = Integer.parseInt(getSocketTimeout());
mongoOptions.threadsAllowedToBlockForConnectionMultiplier = Integer.parseInt(getThreadsAllowedToBlockForConnectionMultiplier());
mongoOptions.w = Integer.parseInt(getWriteOperationNumberOfServers());
mongoOptions.wtimeout = Integer.parseInt(getWriteOperationTimeout());
if(log.isDebugEnabled()) {
log.debug("options : " + mongoOptions.toString());
}
if(getThreadContext().getVariables().getObject(getSource()) != null) {
if(log.isWarnEnabled()) {
log.warn(getSource() + " has already been defined.");
}
}
else {
if(log.isDebugEnabled()) {
log.debug(getSource() + " is being defined.");
}
getThreadContext().getVariables().putObject(getSource(), new MongoDB(MongoUtils.toServerAddresses(getConnection()), mongoOptions));
}
}
@Override
public void testStarted(String s) {
testStarted();
}
@Override
public void testEnded() {
if(log.isDebugEnabled()) {
log.debug(getTitle() + " testEnded");
}
((MongoDB)getThreadContext().getVariables().getObject(getSource())).clear();
}
@Override
public void testEnded(String s) {
testEnded();
}
}

View File

@ -0,0 +1,116 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.config;
import java.beans.PropertyDescriptor;
import org.apache.jmeter.testbeans.BeanInfoSupport;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
*/
public class MongoSourceElementBeanInfo
extends BeanInfoSupport {
private static final Logger log = LoggingManager.getLoggerForClass();
public MongoSourceElementBeanInfo() {
super(MongoSourceElement.class);
//http://api.mongodb.org/java/2.7.2/com/mongodb/Mongo.html
createPropertyGroup("mongodb", new String[] {
"connection",
"source"});
//http://api.mongodb.org/java/2.7.2/com/mongodb/MongoOptions.html/
createPropertyGroup("options", new String[]{
"autoConnectRetry",
"connectionsPerHost",
"connectTimeout",
"maxAutoConnectRetryTime",
"maxWaitTime",
"socketTimeout",
"socketKeepAlive",
"threadsAllowedToBlockForConnectionMultiplier"});
//http://api.mongodb.org/java/2.7.2/com/mongodb/MongoOptions.html/
createPropertyGroup("writeConcern", new String[] {
"fsync",
"safe",
"waitForJournaling",
"writeOperationNumberOfServers",
"writeOperationTimeout" });
PropertyDescriptor p = property("connection");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("source");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("autoConnectRetry");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, Boolean.FALSE);
p = property("connectionsPerHost");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "10");
p = property("connectTimeout");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "0");
p = property("threadsAllowedToBlockForConnectionMultiplier");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "5");
p = property("maxAutoConnectRetryTime");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "0");
p = property("maxWaitTime");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "120000");
p = property("socketTimeout");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "0");
p = property("socketKeepAlive");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, Boolean.FALSE);
p = property("fsync");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, Boolean.FALSE);
p = property("safe");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, Boolean.FALSE);
p = property("waitForJournaling");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, Boolean.FALSE);
p = property("writeOperationNumberOfServers");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "0");
p = property("writeOperationTimeout");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "0");
if(log.isDebugEnabled()) {
for (PropertyDescriptor pd : getPropertyDescriptors()) {
log.debug(pd.getName());
log.debug(pd.getDisplayName());
}
}
}
}

View File

@ -0,0 +1,46 @@
displayName=MongoDB Source Config
mongodb.displayName=MongoDB Connection
mongodb.shortDescription=Configure the connection
connection.displayName=Server Address List
connection.shortDescription=Server Address List
source.displayName=MongoDB Source
source.shortDescription=Configure the Source
options.displayName=MongoDB Options
options.shortDescription=Various settings for the driver
autoConnectRetry.displayName=Keep trying
connectionsPerHost.displayName=Maximum connections Per Host
connectTimeout.displayName=Connection timeout
maxAutoConnectRetryTime.displayName=Maximum retry time
maxWaitTime.displayName=Maximum wait time
socketKeepAlive.displayName=Socket keep alive
socketTimeout.displayName=Socket timeout
threadsAllowedToBlockForConnectionMultiplier.displayName=Block Multiplier
autoConnectRetry.shortDescription=If true, the driver will keep trying to connect to the same server in case that the socket cannot be established.<br><br>There is maximum amount of time to keep retrying, which is 15s by default.<br><br>This can be useful to avoid some exceptions being thrown when a server is down temporarily by blocking the operations.<br><br>It also can be useful to smooth the transition to a new master (so that a new master is elected within the retry time).<br><br>Note that when using this flag:<br>- for a replica set, the driver will trying to connect to the old master for that time, instead of failing over to the new one right away -<br> this does not prevent exception from being thrown in read/write operations on the socket, which must be handled by application.<br><br>Even if this flag is false, the driver already has mechanisms to automatically recreate broken connections and retry the read operations. <br><br>Default is false.
connectionsPerHost.shortDescription=The maximum number of connections allowed per host for this Mongo instance.<br><br>Those connections will be kept in a pool when idle.<br><br>Once the pool is exhausted, any operation requiring a connection will block waiting for an available connection.<br><br>Default is 10.
connectTimeout.shortDescription=The connection timeout in milliseconds.<br><br>It is used solely when establishing a new connection Socket.connect(java.net.SocketAddress, int)<br><br>Default is 0 and means no timeout.
maxAutoConnectRetryTime.shortDescription=The maximum amount of time in MS to spend retrying to open connection to the same server.<br><br>Default is 0, which means to use the default 15s if autoConnectRetry is on.
maxWaitTime.shortDescription=The maximum wait time in ms that a thread may wait for a connection to become available.<br><br>Default is 120,000.
socketKeepAlive.shortDescription=This flag controls the socket keep alive feature that keeps a connection alive through firewalls Socket.setKeepAlive(boolean)<br><br>Default is false.
socketTimeout.shortDescription=The socket timeout in milliseconds It is used for I/O socket read and write operations Socket.setSoTimeout(int)<br><br>Default is 0 and means no timeout.
threadsAllowedToBlockForConnectionMultiplier.shortDescription=This multiplier, multiplied with the connectionsPerHost setting, gives the maximum number of threads that may be waiting for a connection to become available from the pool.<br><br>All further threads will get an exception right away.<br><br>For example if connectionsPerHost is 10 and threadsAllowedToBlockForConnectionMultiplier is 5, then up to 50 threads can wait for a connection.<br><br>Default is 5.
writeConcern.displayName=Write Concern Options
writeConcern.shortDescription=Various settings for the driver
fsync.displayName=Fsync
safe.displayName=Safe
waitForJournaling.displayName=Wait for Journal
writeOperationNumberOfServers.displayName=Wait for Servers
writeOperationTimeout.displayName=Wait Timeout
fsync.shortDescription=The fsync value of the global WriteConcern.<br><br>Default is false.
safe.shortDescription=If true the driver will use a WriteConcern of WriteConcern.SAFE for all operations.<br><br>If w, wtimeout, fsync or j are specified, this setting is ignored.<br><br>Default is false.
waitForJournaling.shortDescription=The j value of the global WriteConcern.<br><br>Default is false.
writeOperationNumberOfServers.shortDescription=The w value of the global WriteConcern.<br><br>Default is 0.
writeOperationTimeout.shortDescription=The wtimeout value of the global WriteConcern.<br><br>Default is 0.

View File

@ -0,0 +1,46 @@
displayName=MongoDB Source Config
mongodb.displayName=MongoDB Connection
mongodb.shortDescription=Configure the connection
connection.displayName=Server Address List
connection.shortDescription=Server Address List
source.displayName=MongoDB Source
source.shortDescription=Configure the Source
options.displayName=MongoDB Options
options.shortDescription=Various settings for the driver
autoConnectRetry.displayName=Keep trying
connectionsPerHost.displayName=Maximum connections Per Host
connectTimeout.displayName=Connection timeout
maxAutoConnectRetryTime.displayName=Maximum retry time
maxWaitTime.displayName=Maximum wait time
socketKeepAlive.displayName=Socket keep alive
socketTimeout.displayName=Socket timeout
threadsAllowedToBlockForConnectionMultiplier.displayName=Block Multiplier
autoConnectRetry.shortDescription=If true, the driver will keep trying to connect to the same server in case that the socket cannot be established.<br><br>There is maximum amount of time to keep retrying, which is 15s by default.<br><br>This can be useful to avoid some exceptions being thrown when a server is down temporarily by blocking the operations.<br><br>It also can be useful to smooth the transition to a new master (so that a new master is elected within the retry time).<br><br>Note that when using this flag:<br>- for a replica set, the driver will trying to connect to the old master for that time, instead of failing over to the new one right away -<br> this does not prevent exception from being thrown in read/write operations on the socket, which must be handled by application.<br><br>Even if this flag is false, the driver already has mechanisms to automatically recreate broken connections and retry the read operations. <br><br>Default is false.
connectionsPerHost.shortDescription=The maximum number of connections allowed per host for this Mongo instance.<br><br>Those connections will be kept in a pool when idle.<br><br>Once the pool is exhausted, any operation requiring a connection will block waiting for an available connection.<br><br>Default is 10.
connectTimeout.shortDescription=The connection timeout in milliseconds.<br><br>It is used solely when establishing a new connection Socket.connect(java.net.SocketAddress, int)<br><br>Default is 0 and means no timeout.
maxAutoConnectRetryTime.shortDescription=The maximum amount of time in MS to spend retrying to open connection to the same server.<br><br>Default is 0, which means to use the default 15s if autoConnectRetry is on.
maxWaitTime.shortDescription=The maximum wait time in ms that a thread may wait for a connection to become available.<br><br>Default is 120,000.
socketKeepAlive.shortDescription=This flag controls the socket keep alive feature that keeps a connection alive through firewalls Socket.setKeepAlive(boolean)<br><br>Default is false.
socketTimeout.shortDescription=The socket timeout in milliseconds It is used for I/O socket read and write operations Socket.setSoTimeout(int)<br><br>Default is 0 and means no timeout.
threadsAllowedToBlockForConnectionMultiplier.shortDescription=This multiplier, multiplied with the connectionsPerHost setting, gives the maximum number of threads that may be waiting for a connection to become available from the pool.<br><br>All further threads will get an exception right away.<br><br>For example if connectionsPerHost is 10 and threadsAllowedToBlockForConnectionMultiplier is 5, then up to 50 threads can wait for a connection.<br><br>Default is 5.
writeConcern.displayName=Write Concern Options
writeConcern.shortDescription=Various settings for the driver
fsync.displayName=Fsync
safe.displayName=Safe
waitForJournaling.displayName=Wait for Journal
writeOperationNumberOfServers.displayName=Wait for Servers
writeOperationTimeout.displayName=Wait Timeout
fsync.shortDescription=The fsync value of the global WriteConcern.<br><br>Default is false.
safe.shortDescription=If true the driver will use a WriteConcern of WriteConcern.SAFE for all operations.<br><br>If w, wtimeout, fsync or j are specified, this setting is ignored.<br><br>Default is false.
waitForJournaling.shortDescription=The j value of the global WriteConcern.<br><br>Default is false.
writeOperationNumberOfServers.shortDescription=The w value of the global WriteConcern.<br><br>Default is 0.
writeOperationTimeout.shortDescription=The wtimeout value of the global WriteConcern.<br><br>Default is 0.

View File

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.mongo;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
/**
*/
public class EvalResultHandler {
//This can lead to code smell, meh! Do we care
public String handle(Object o) {
if(o == null) {
return "ok";
}
if(o instanceof Double) {
return this.handle((Double)o);
}
else if(o instanceof Integer) {
return this.handle((Integer)o);
}
else if(o instanceof String) {
return this.handle((String)o);
}
else if(o instanceof DBObject) {
return this.handle((DBObject)o);
}
else {
return "return type not handled";
}
}
public String handle(Integer o) {
return o.toString();
}
public String handle(String o) {
return o;
}
public String handle(Double o) {
return o.toString();
}
public String handle(DBObject o) {
return JSON.serialize(o);
}
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.mongo;
import java.util.List;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;
/**
*/
public class MongoDB {
private static final Logger log = LoggingManager.getLoggerForClass();
// Mongo is Thread Safe
private Mongo mongo = null;
public MongoDB(
List<ServerAddress> serverAddresses,
MongoOptions mongoOptions) {
mongo = new Mongo(serverAddresses, mongoOptions);
}
public DB getDB(String database, String username, String password) {
if(log.isDebugEnabled()) {
log.debug("username: " + username+", password: " + password+", database: " + database);
}
DB db = mongo.getDB(database);
boolean authenticated = db.isAuthenticated();
if(!authenticated) {
if(username != null && password != null && username.length() > 0 && password.length() > 0) {
authenticated = db.authenticate(username, password.toCharArray());
}
}
if(log.isDebugEnabled()) {
log.debug("authenticated: " + authenticated);
}
return db;
}
public void clear() {
if(log.isDebugEnabled()) {
log.debug("clearing");
}
mongo.close();
//there is no harm in trying to clear up
mongo = null;
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.mongo;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import com.mongodb.ServerAddress;
/**
*/
public class MongoUtils {
private static final Logger log = LoggingManager.getLoggerForClass();
public static ArrayList<ServerAddress> toServerAddresses(String connections) {
ArrayList<ServerAddress> addresses = new ArrayList<ServerAddress>();
try {
for(String connection : Arrays.asList(connections.split(","))) {
int port = 27017;
String[] hostPort = connection.split(":");
if(hostPort.length > 1 && hostPort[1] != null) {
port = Integer.parseInt(hostPort[1].trim());
}
addresses.add(new ServerAddress(hostPort[0], port));
}
}
catch(UnknownHostException uhe) {
if(log.isWarnEnabled()) {
log.warn("", uhe);
}
}
return addresses;
}
}

View File

@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.sampler;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import com.mongodb.DB;
/**
*/
public class MongoScriptRunner {
private static final Logger log = LoggingManager.getLoggerForClass();
public MongoScriptRunner() {
super();
}
/**
*
* @param db
* @param script
* @return
* @throws Exception
*/
public Object evaluate(DB db, String script)
throws Exception {
if(log.isDebugEnabled()) {
log.debug("database: " + db.getName()+", script: " + script);
}
db.requestStart();
try {
db.requestEnsureConnection();
Object result = db.eval(script);
if(log.isDebugEnabled()) {
log.debug("Result : " + result);
}
return result;
} finally {
db.requestDone();
}
}
}

View File

@ -0,0 +1,150 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.sampler;
import org.apache.jmeter.protocol.mongodb.config.MongoSourceElement;
import org.apache.jmeter.protocol.mongodb.mongo.EvalResultHandler;
import org.apache.jmeter.protocol.mongodb.mongo.MongoDB;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testbeans.TestBean;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import com.mongodb.DB;
/**
*/
public class MongoScriptSampler
extends AbstractSampler
implements TestBean {
private static final Logger log = LoggingManager.getLoggerForClass();
public final static String SOURCE = "MongoScriptSampler.source"; //$NON-NLS-1$
public final static String DATABASE = "MongoScriptSampler.database"; //$NON-NLS-1$
public final static String USERNAME = "MongoScriptSampler.username"; //$NON-NLS-1$
public final static String PASSWORD = "MongoScriptSampler.password"; //$NON-NLS-1$
public final static String SCRIPT = "MongoScriptSampler.script"; //$NON-NLS-1$
private static final long serialVersionUID = -7789012234636439896L;
public MongoScriptSampler() {
trace("MongoScriptSampler()");
}
@Override
public SampleResult sample(Entry e) {
trace("sample()");
SampleResult res = new SampleResult();
String data = getScript();
res.setSampleLabel(getTitle());
res.setResponseCodeOK();
res.setResponseCode("200");
res.setSuccessful(true);
res.setResponseMessageOK();
res.setSamplerData(data);
res.setDataType(SampleResult.TEXT);
res.setContentType("text/plain"); // $NON-NLS-1$
res.sampleStart();
try {
MongoDB mongoDB = MongoSourceElement.getMongoDB(getSource());
MongoScriptRunner runner = new MongoScriptRunner();
DB db = mongoDB.getDB(getDatabase(), getUsername(), getPassword());
res.latencyEnd();
Object result = runner.evaluate(db, data);
res.sampleEnd();
EvalResultHandler handler = new EvalResultHandler();
String resultAsString = handler.handle(result);
res.setResponseData(resultAsString.getBytes());
}
catch (Exception ex) {
res.sampleEnd();
log.warn("", ex);
res.setResponseCode("500");// $NON-NLS-1$
res.setSuccessful(false);
res.setResponseMessage(ex.toString());
res.setResponseData(ex.getMessage().getBytes());
}
finally {
res.sampleEnd();
}
return res;
}
public String getTitle() {
return this.getName();
}
public String getScript() {
return getPropertyAsString(SCRIPT);
}
public void setScript(String script) {
setProperty(SCRIPT, script);
}
public String getDatabase() {
return getPropertyAsString(DATABASE);
}
public void setDatabase(String database) {
setProperty(DATABASE, database);
}
public String getUsername() {
return getPropertyAsString(USERNAME);
}
public void setUsername(String username) {
setProperty(USERNAME, username);
}
public String getPassword() {
return getPropertyAsString(PASSWORD);
}
public void setPassword(String password) {
setProperty(PASSWORD, password);
}
public String getSource() {
return getPropertyAsString(SOURCE);
}
public void setSource(String source) {
setProperty(SOURCE, source);
}
/*
* Helper
*/
private void trace(String s) {
if(log.isDebugEnabled()) {
log.debug(Thread.currentThread().getName() + " (" + getTitle() + " " + s + " " + this.toString());
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.protocol.mongodb.sampler;
import java.beans.PropertyDescriptor;
import org.apache.jmeter.testbeans.BeanInfoSupport;
import org.apache.jmeter.testbeans.gui.TextAreaEditor;
import org.apache.jmeter.testbeans.gui.TypeEditor;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
*/
public class MongoScriptSamplerBeanInfo
extends BeanInfoSupport {
private static final Logger log = LoggingManager.getLoggerForClass();
public MongoScriptSamplerBeanInfo() {
super(MongoScriptSampler.class);
//http://api.mongodb.org/java/2.7.2/com/mongodb/Mongo.html
createPropertyGroup("mongodb", new String[] {
"source",
"database",
"username",
"password" });
createPropertyGroup("sampler", new String[]{
"script"});
PropertyDescriptor p = property("database");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("username");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("password", TypeEditor.PasswordEditor);
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("source");
p.setValue(NOT_UNDEFINED, Boolean.TRUE);
p.setValue(DEFAULT, "");
p = property("script");
p.setValue(NOT_UNDEFINED, Boolean.FALSE);
p.setValue(DEFAULT, "");
p.setValue(NOT_EXPRESSION, Boolean.TRUE);
p.setPropertyEditorClass(TextAreaEditor.class);
if(log.isDebugEnabled()) {
for (PropertyDescriptor pd : getPropertyDescriptors()) {
log.debug(pd.getName());
log.debug(pd.getDisplayName());
}
}
}
}

View File

@ -0,0 +1,14 @@
displayName=MongoDB Script
mongodb.displayName=MongoDB Connection
mongodb.shortDescription=Configure the connection
source.displayName=MongoDB Source
source.shortDescription=Configure the Source
database.displayName=Database Name
username.displayName=Username
password.displayName=Password
sampler.displayName=Script
script.displayName=The script to run
script.shortDescription=Add your mongo shell script as you would via the mongo shell.

View File

@ -0,0 +1,14 @@
displayName=MongoDB Script
mongodb.displayName=MongoDB Connection
mongodb.shortDescription=Configure the connection
source.displayName=MongoDB Source
source.shortDescription=Configure the Source
database.displayName=Database Name
username.displayName=Username
password.displayName=Password
sampler.displayName=Script
script.displayName=The script to run
script.shortDescription=Add your mongo shell script as you would via the mongo shell.

View File

@ -167,6 +167,7 @@ This does not affect JMeter operation.
<h3>General</h3>
<ul>
<li><bugzilla>54584</bugzilla> - MongoDB plugin</li>
</ul>
<h2>Non-functional changes</h2>

View File

@ -1862,6 +1862,17 @@ If omitted, output is captured and returned as the response data.</property>
<property name="Expected Return Code" required="No">Expected return code for System Call, required if "Check Return Code" is checked.</property>
</component>
<component name="MongoDB Script" index="&sect-num;.1.21" width="519" height="289" screenshot="mongodb-sampler.png">
<description>
TODO</description>
<properties>
</properties>
<links>
</links>
</component>
<a href="#">^</a>
</section>
@ -3921,6 +3932,16 @@ GUI that they can use while developing new JMeter components.</p>
</component>
<component name="MongoDB Source Config" index="&sect-num;.4.18" width="519" height="289" screenshot="mongodb-config.png">
<description>
TODO</description>
<properties>
</properties>
<links>
</links>
</component>
<a href="#">^</a>