Lines 28-39
Link Here
|
28 |
import java.net.URL; |
28 |
import java.net.URL; |
29 |
import java.security.MessageDigest; |
29 |
import java.security.MessageDigest; |
30 |
import java.security.NoSuchAlgorithmException; |
30 |
import java.security.NoSuchAlgorithmException; |
|
|
31 |
import java.util.ArrayList; |
31 |
import java.util.Arrays; |
32 |
import java.util.Arrays; |
32 |
import java.util.Collections; |
33 |
import java.util.Collections; |
33 |
import java.util.HashMap; |
34 |
import java.util.HashMap; |
34 |
import java.util.Iterator; |
35 |
import java.util.Iterator; |
35 |
import java.util.List; |
36 |
import java.util.List; |
36 |
import java.util.Map; |
37 |
import java.util.Map; |
|
|
38 |
import java.util.concurrent.Callable; |
39 |
import java.util.concurrent.ExecutionException; |
40 |
import java.util.concurrent.Future; |
41 |
import java.util.concurrent.LinkedBlockingQueue; |
42 |
import java.util.concurrent.ThreadPoolExecutor; |
43 |
import java.util.concurrent.TimeUnit; |
37 |
|
44 |
|
38 |
import org.apache.commons.io.IOUtils; |
45 |
import org.apache.commons.io.IOUtils; |
39 |
import org.apache.jmeter.config.Argument; |
46 |
import org.apache.jmeter.config.Argument; |
Lines 48-56
Link Here
|
48 |
import org.apache.jmeter.protocol.http.util.ConversionUtils; |
55 |
import org.apache.jmeter.protocol.http.util.ConversionUtils; |
49 |
import org.apache.jmeter.protocol.http.util.EncoderCache; |
56 |
import org.apache.jmeter.protocol.http.util.EncoderCache; |
50 |
import org.apache.jmeter.protocol.http.util.HTTPArgument; |
57 |
import org.apache.jmeter.protocol.http.util.HTTPArgument; |
|
|
58 |
import org.apache.jmeter.protocol.http.util.HTTPConstantsInterface; |
51 |
import org.apache.jmeter.protocol.http.util.HTTPFileArg; |
59 |
import org.apache.jmeter.protocol.http.util.HTTPFileArg; |
52 |
import org.apache.jmeter.protocol.http.util.HTTPFileArgs; |
60 |
import org.apache.jmeter.protocol.http.util.HTTPFileArgs; |
53 |
import org.apache.jmeter.protocol.http.util.HTTPConstantsInterface; |
|
|
54 |
import org.apache.jmeter.samplers.AbstractSampler; |
61 |
import org.apache.jmeter.samplers.AbstractSampler; |
55 |
import org.apache.jmeter.samplers.Entry; |
62 |
import org.apache.jmeter.samplers.Entry; |
56 |
import org.apache.jmeter.samplers.SampleResult; |
63 |
import org.apache.jmeter.samplers.SampleResult; |
Lines 139-149
Link Here
|
139 |
public static final String DO_MULTIPART_POST = "HTTPSampler.DO_MULTIPART_POST"; // $NON-NLS-1$ |
146 |
public static final String DO_MULTIPART_POST = "HTTPSampler.DO_MULTIPART_POST"; // $NON-NLS-1$ |
140 |
|
147 |
|
141 |
public static final String BROWSER_COMPATIBLE_MULTIPART = "HTTPSampler.BROWSER_COMPATIBLE_MULTIPART"; // $NON-NLS-1$ |
148 |
public static final String BROWSER_COMPATIBLE_MULTIPART = "HTTPSampler.BROWSER_COMPATIBLE_MULTIPART"; // $NON-NLS-1$ |
|
|
149 |
|
150 |
public static final String CONCURRENT_DWN = "HTTPSampler.concurrentDwn"; // $NON-NLS-1$ |
151 |
|
152 |
public static final String CONCURRENT_POOL = "HTTPSampler.concurrentPool"; // $NON-NLS-1$ |
142 |
|
153 |
|
143 |
//- JMX names |
154 |
//- JMX names |
144 |
|
155 |
|
145 |
public static final boolean BROWSER_COMPATIBLE_MULTIPART_MODE_DEFAULT = false; // The default setting to be used (i.e. historic) |
156 |
public static final boolean BROWSER_COMPATIBLE_MULTIPART_MODE_DEFAULT = false; // The default setting to be used (i.e. historic) |
146 |
|
157 |
|
|
|
158 |
private static final long KEEPALIVETIME = 0; // for Thread Pool for resources but no need to use a special value? |
159 |
|
160 |
private static final long AWAIT_TERMINATION_TIMEOUT = |
161 |
JMeterUtils.getPropDefault("httpsampler.await_termination_timeout", 60); // $NON-NLS-1$ // default value: 60 secs |
162 |
|
163 |
public static final int CONCURRENT_POOL_SIZE = 4; // Default concurrent pool size for download embedded resources |
164 |
|
147 |
|
165 |
|
148 |
public static final String DEFAULT_METHOD = GET; // $NON-NLS-1$ |
166 |
public static final String DEFAULT_METHOD = GET; // $NON-NLS-1$ |
149 |
// Supported methods: |
167 |
// Supported methods: |
Lines 1107-1112
Link Here
|
1107 |
log.warn("Ignoring embedded URL match string: "+e.getMessage()); |
1125 |
log.warn("Ignoring embedded URL match string: "+e.getMessage()); |
1108 |
} |
1126 |
} |
1109 |
} |
1127 |
} |
|
|
1128 |
|
1129 |
// For concurrent get resources |
1130 |
final ArrayList<ASyncSample> liste = new ArrayList<ASyncSample>(); |
1131 |
|
1110 |
while (urls.hasNext()) { |
1132 |
while (urls.hasNext()) { |
1111 |
Object binURL = urls.next(); // See catch clause below |
1133 |
Object binURL = urls.next(); // See catch clause below |
1112 |
try { |
1134 |
try { |
Lines 1129-1137
Link Here
|
1129 |
if (pattern != null && localMatcher != null && !localMatcher.matches(urlStrEnc, pattern)) { |
1151 |
if (pattern != null && localMatcher != null && !localMatcher.matches(urlStrEnc, pattern)) { |
1130 |
continue; // we have a pattern and the URL does not match, so skip it |
1152 |
continue; // we have a pattern and the URL does not match, so skip it |
1131 |
} |
1153 |
} |
1132 |
HTTPSampleResult binRes = sample(url, GET, false, frameDepth + 1); |
1154 |
|
1133 |
res.addSubResult(binRes); |
1155 |
if (isConcurrentDwn()) { |
1134 |
res.setSuccessful(res.isSuccessful() && binRes.isSuccessful()); |
1156 |
// if concurrent download emb. resources, add to a list for async gets later |
|
|
1157 |
liste.add(new ASyncSample(url, GET, false, frameDepth + 1)); |
1158 |
} else { |
1159 |
// default: serial download embedded resources |
1160 |
HTTPSampleResult binRes = sample(url, GET, false, frameDepth + 1); |
1161 |
res.addSubResult(binRes); |
1162 |
res.setSuccessful(res.isSuccessful() && binRes.isSuccessful()); |
1163 |
} |
1164 |
|
1135 |
} |
1165 |
} |
1136 |
} catch (ClassCastException e) { // TODO can this happen? |
1166 |
} catch (ClassCastException e) { // TODO can this happen? |
1137 |
res.addSubResult(errorResult(new Exception(binURL + " is not a correct URI"), res)); |
1167 |
res.addSubResult(errorResult(new Exception(binURL + " is not a correct URI"), res)); |
Lines 1139-1144
Link Here
|
1139 |
continue; |
1169 |
continue; |
1140 |
} |
1170 |
} |
1141 |
} |
1171 |
} |
|
|
1172 |
|
1173 |
// IF for download concurrent embedded resources |
1174 |
if (isConcurrentDwn()) { |
1175 |
int poolSize = CONCURRENT_POOL_SIZE; // init with default value |
1176 |
try { |
1177 |
poolSize = Integer.parseInt(getConcurrentPool()); |
1178 |
} catch (NumberFormatException nfe) { |
1179 |
log.warn("Concurrent download resources selected, "// $NON-NLS-1$ |
1180 |
+ "but pool size value is bad. Use default value");// $NON-NLS-1$ |
1181 |
} |
1182 |
// Thread pool Executor to get resources |
1183 |
// use a LinkedBlockingQueue, note: max pool size doesn't effect |
1184 |
final ThreadPoolExecutor exec = new ThreadPoolExecutor( |
1185 |
poolSize, poolSize, KEEPALIVETIME, TimeUnit.SECONDS, |
1186 |
new LinkedBlockingQueue<Runnable>()); |
1187 |
|
1188 |
try { |
1189 |
// sample all resources with threadpool |
1190 |
final List<Future<HTTPSampleResult>> retExec = exec.invokeAll(liste); |
1191 |
// call normal shutdown (wait ending all tasks) |
1192 |
exec.shutdown(); |
1193 |
// put a timeout if tasks couldn't terminate |
1194 |
exec.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.SECONDS); |
1195 |
|
1196 |
// add result to main sampleResult |
1197 |
for (Future<HTTPSampleResult> future : retExec) { |
1198 |
final HTTPSampleResult binRes = future.get(); |
1199 |
res.addSubResult(binRes); |
1200 |
res.setSuccessful(res.isSuccessful() && binRes.isSuccessful()); |
1201 |
} |
1202 |
} catch (InterruptedException ie) { |
1203 |
log.warn("Interruped fetching embedded resources", ie); // $NON-NLS-1$ |
1204 |
} catch (ExecutionException ee) { |
1205 |
log.warn("Execution issue when fetching embedded resources", ee); // $NON-NLS-1$ |
1206 |
} |
1207 |
} |
1142 |
} |
1208 |
} |
1143 |
return res; |
1209 |
return res; |
1144 |
} |
1210 |
} |
Lines 1565-1569
Link Here
|
1565 |
public String getIpSource() { |
1631 |
public String getIpSource() { |
1566 |
return getPropertyAsString(IP_SOURCE,""); |
1632 |
return getPropertyAsString(IP_SOURCE,""); |
1567 |
} |
1633 |
} |
|
|
1634 |
|
1635 |
/** |
1636 |
* Return if used a concurrent thread pool to get embedded resources. |
1637 |
* |
1638 |
* @return true if used |
1639 |
*/ |
1640 |
public boolean isConcurrentDwn() { |
1641 |
return getPropertyAsBoolean(CONCURRENT_DWN); |
1642 |
} |
1643 |
|
1644 |
public void setConcurrentDwn(boolean concurrentDwn) { |
1645 |
setProperty(new BooleanProperty(CONCURRENT_DWN, concurrentDwn)); |
1646 |
} |
1647 |
/** |
1648 |
* Get the pool size for concurrent thread pool to get embedded resources. |
1649 |
* |
1650 |
* @return the pool size |
1651 |
*/ |
1652 |
public String getConcurrentPool() { |
1653 |
return getPropertyAsString(CONCURRENT_POOL,"4"); |
1654 |
} |
1655 |
|
1656 |
public void setConcurrentPool(String poolSize) { |
1657 |
setProperty(new StringProperty(CONCURRENT_POOL, poolSize)); |
1658 |
} |
1659 |
|
1660 |
/** |
1661 |
* Callable class to sample asynchronously resources embedded |
1662 |
* |
1663 |
*/ |
1664 |
public class ASyncSample implements Callable<HTTPSampleResult> { |
1665 |
final private URL url; |
1666 |
final private String method; |
1667 |
final private boolean areFollowingRedirect; |
1668 |
final private int depth; |
1669 |
|
1670 |
public ASyncSample(URL url, String method, |
1671 |
boolean areFollowingRedirect, int depth){ |
1672 |
this.url = url; |
1673 |
this.method = method; |
1674 |
this.areFollowingRedirect = areFollowingRedirect; |
1675 |
this.depth = depth; |
1676 |
} |
1677 |
|
1678 |
public HTTPSampleResult call() { |
1679 |
return sample(url, method, areFollowingRedirect, depth); |
1680 |
} |
1681 |
} |
1568 |
} |
1682 |
} |
1569 |
|
1683 |
|