Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit 26947e4

Browse files
authored
Merge pull request #546 from ThomasMarquardt/legacy-dev
SAXParser concurrency bug causes list results to appear empty
2 parents 82e86f4 + 15b176d commit 26947e4

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobContainerTests.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@
2222
import java.net.URISyntaxException;
2323
import java.security.InvalidKeyException;
2424
import java.util.*;
25+
import java.util.concurrent.Executors;
26+
import java.util.concurrent.ThreadPoolExecutor;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
import javax.xml.parsers.SAXParser;
2530

2631
import com.microsoft.azure.storage.*;
32+
import com.microsoft.azure.storage.core.Utility;
2733
import org.junit.After;
2834
import org.junit.Before;
2935
import org.junit.Test;
@@ -541,6 +547,49 @@ public void testCloudBlobContainerListBlobs() throws StorageException, IOExcepti
541547
assertTrue(blobNames.size() == 0);
542548
}
543549

550+
@Test
551+
@Category({DevFabricTests.class, DevStoreTests.class})
552+
public void testSAXParserConcurrency() throws Exception {
553+
final int totalCount = 200000;
554+
final int numThreads = 200;
555+
final AtomicInteger currentCount = new AtomicInteger(0);
556+
final AtomicInteger pending = new AtomicInteger(0);
557+
final AtomicInteger failureCount = new AtomicInteger(0);
558+
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numThreads);
559+
560+
do {
561+
final int count = currentCount.incrementAndGet();
562+
pending.incrementAndGet();
563+
executor.execute(new Runnable() {
564+
@Override
565+
public void run() {
566+
pending.decrementAndGet();
567+
if (count > totalCount) {
568+
return;
569+
}
570+
try {
571+
SAXParser parser = Utility.getSAXParser();
572+
if (!parser.isNamespaceAware()) {
573+
failureCount.incrementAndGet();
574+
}
575+
assertEquals(true, parser.isNamespaceAware());
576+
} catch (Exception e) {
577+
fail(e.toString());
578+
}
579+
}
580+
});
581+
582+
assertEquals(0, failureCount.get());
583+
584+
while (pending.get() > numThreads * 2) {
585+
Thread.sleep(10);
586+
}
587+
} while (currentCount.get() < totalCount);
588+
executor.shutdown();
589+
executor.awaitTermination(1, TimeUnit.MINUTES);
590+
executor.shutdownNow();
591+
}
592+
544593
/**
545594
* List the blobs in a container with a prefix
546595
*

microsoft-azure-storage/src/com/microsoft/azure/storage/core/Utility.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ protected DateFormat initialValue() {
129129
* Thread local for SAXParser.
130130
*/
131131
private static final ThreadLocal<SAXParser> saxParserThreadLocal = new ThreadLocal<SAXParser>() {
132-
SAXParserFactory factory;
133132
@Override public SAXParser initialValue() {
134-
factory = SAXParserFactory.newInstance();
133+
SAXParserFactory factory = SAXParserFactory.newInstance();
135134
factory.setNamespaceAware(true);
136135
try {
137136
return factory.newSAXParser();

0 commit comments

Comments
 (0)