
|
If you were logged in you would be able to see more operations.
|
|
|
|
Environment:
|
sun 1.4.2_04, jrockit 1.4.2_04, multi-cpu machine
|
|
| Resolution Date: |
02/Mar/06 05:47 AM
|
|
When using validate() method in multi-threaded, multi-cpu environment, there is a pretty high probability of getting false XMLErrors for elements defined with regex patterns in schema.
import EDU.oswego.cs.dl.util.concurrent.CountDown;
import junit.framework.TestCase;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlError;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
public class XmlBeansTest extends TestCase {
public void testMultipleThreads() throws XmlException, InterruptedException {
final int totalThreadCount = 100;
CountDown latch = new CountDown(totalThreadCount);
CountDown start = new CountDown(1);
long now = System.currentTimeMillis();
System.out.println("Starting");
for (int i = 0; i < totalThreadCount; i++) {
new ParseAndValidate(latch, start).start();
}
start.release();
latch.acquire();
System.out.println("Finished: " + (System.currentTimeMillis() - now));
}
public static void main(String[] args) throws Exception, InterruptedException {
XmlBeansTest xmlBeansTest = new XmlBeansTest();
xmlBeansTest.setUp();
xmlBeansTest.testMultipleThreads();
}
private class ParseAndValidate extends Thread {
private CountDown countDownLatch;
private CountDown start;
private final String xmldata = ...;
public ParseAndValidate(CountDown countDownLatch, CountDown start) {
this.countDownLatch = countDownLatch;
this.start = start;
}
public void run() {
try {
start.acquire();
boolean valid = parseAndValidate();
if (!valid) {
System.out.println("Not Valid!!!");
}
countDownLatch.release();
} catch (XmlException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private boolean parseAndValidate() throws XmlException {
MyXml xml = MyXml.Factory.parse(xmldata);
return validate(xml);
}
private boolean validate(MyXml rdd) {
Collection errors = new ArrayList();
XmlOptions validateOptions = new XmlOptions();
validateOptions.setErrorListener(errors);
boolean valid = rdd.validate(validateOptions);
if (!valid) {
for (Iterator iterator = errors.iterator(); iterator.hasNext();) {
XmlError xmlError = (XmlError) iterator.next();
System.out.println("XML Error - " + xmlError.getMessage() + " at\n" + xmlError.getCursorLocation().xmlText());
}
}
return valid;
}
}
}
The code above, when executed on a MP machine, has a pretty high probability (5%+ I'd say) of generating at least one failed validation. On machines with hyperthreading, the probability is even higher (10%+).
I only saw it fail on regex patterns. On SP machines it never fails. The only workaround I've found is encasing a validate method in a globally synchronised block (not really a workaround, I know).
The code also runs very slowly on MP machines with sun jdk, but that's unrelated to the problem I guess.
|
|
Description
|
When using validate() method in multi-threaded, multi-cpu environment, there is a pretty high probability of getting false XMLErrors for elements defined with regex patterns in schema.
import EDU.oswego.cs.dl.util.concurrent.CountDown;
import junit.framework.TestCase;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlError;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
public class XmlBeansTest extends TestCase {
public void testMultipleThreads() throws XmlException, InterruptedException {
final int totalThreadCount = 100;
CountDown latch = new CountDown(totalThreadCount);
CountDown start = new CountDown(1);
long now = System.currentTimeMillis();
System.out.println("Starting");
for (int i = 0; i < totalThreadCount; i++) {
new ParseAndValidate(latch, start).start();
}
start.release();
latch.acquire();
System.out.println("Finished: " + (System.currentTimeMillis() - now));
}
public static void main(String[] args) throws Exception, InterruptedException {
XmlBeansTest xmlBeansTest = new XmlBeansTest();
xmlBeansTest.setUp();
xmlBeansTest.testMultipleThreads();
}
private class ParseAndValidate extends Thread {
private CountDown countDownLatch;
private CountDown start;
private final String xmldata = ...;
public ParseAndValidate(CountDown countDownLatch, CountDown start) {
this.countDownLatch = countDownLatch;
this.start = start;
}
public void run() {
try {
start.acquire();
boolean valid = parseAndValidate();
if (!valid) {
System.out.println("Not Valid!!!");
}
countDownLatch.release();
} catch (XmlException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private boolean parseAndValidate() throws XmlException {
MyXml xml = MyXml.Factory.parse(xmldata);
return validate(xml);
}
private boolean validate(MyXml rdd) {
Collection errors = new ArrayList();
XmlOptions validateOptions = new XmlOptions();
validateOptions.setErrorListener(errors);
boolean valid = rdd.validate(validateOptions);
if (!valid) {
for (Iterator iterator = errors.iterator(); iterator.hasNext();) {
XmlError xmlError = (XmlError) iterator.next();
System.out.println("XML Error - " + xmlError.getMessage() + " at\n" + xmlError.getCursorLocation().xmlText());
}
}
return valid;
}
}
}
The code above, when executed on a MP machine, has a pretty high probability (5%+ I'd say) of generating at least one failed validation. On machines with hyperthreading, the probability is even higher (10%+).
I only saw it fail on regex patterns. On SP machines it never fails. The only workaround I've found is encasing a validate method in a globally synchronised block (not really a workaround, I know).
The code also runs very slowly on MP machines with sun jdk, but that's unrelated to the problem I guess.
|
Show » |
| No work has yet been logged on this issue.
|
|