I put the test cases into the JIRA: https://issues.apache.org/jira/secure/attachment/12365164/epr-tests.zip
Oliver -------- Original-Nachricht -------- > Datum: Wed, 5 Sep 2007 13:20:21 +0200 > Von: [EMAIL PROTECTED] > An: [email protected] > Betreff: RE: RE: EMPTY_DOC thread stability issues > Hi All, > > Any piece of code that uses nodelists will be thread unsafe as soon as a > document is shared across threads. It doesn't matter if the original EPR > has a seperate document or not. The problem with TLSing the Document itself > is that the standard says its not thread safe either, all that happens is > push the problem further down the line until two threads try to nodelist the > same document. > > point 1) affects this directly, the problem is that both the getChildNodes > optimisation and the importing (as Vinh just showed) aren't thread safe. > > For EPRs at least the only way to be truly thread safe is to store the > actual information in raw xml strings (or objects) and re-parse it every time > you use an epr. Its expensive to then reparse but at least safe. > > point 2) is exactly the same problem just pushed further down the line. > The resource EPR with its seperate document is then read simultaneously by > seperate threads wishing to publish events leading to same issue. > getFirstChild/getNextSibling help with this but only as another hack tied to a > specific version of xerces. > > Please upload the test case, the more test cases we can use the better. > > cheers, > Chris > > -----Original Message----- > From: Oliver Waeldrich [mailto:[EMAIL PROTECTED] > Sent: Wednesday, September 05, 2007 12:52 PM > To: [email protected] > Subject: Re: RE: EMPTY_DOC thread stability issues > > > Hi all, > > I did some additional testing related to the EMPTY_DOC problem. Therefore > I set up a test where multiple threads created new EPRs based on a set of > existing (shared) EPRs. Such shared EPRs are resource EPRs (e.g. > notification producer EPR). In this test two different kinds of exceptions > are thrown: > > 1.) > java.lang.NullPointerException > at org.apache.xerces.dom.ParentNode.nodeListItem(Unknown Source) > at org.apache.xerces.dom.ParentNode.item(Unknown Source) > at org.apache.muse.util.xml.XmlUtils.getAllElements(XmlUtils.java:932) > at org.apache.muse.util.xml.XmlUtils.getElement(XmlUtils.java:1144) > at org.apache.muse.util.xml.XmlUtils.getElement(XmlUtils.java:1119) > at > org.apache.muse.test.case1.TestEndpointReference.initializeFromXML(TestEndpointReference.java:560) > at > org.apache.muse.test.case1.TestEndpointReference.<init>(TestEndpointReference.java:193) > at org.apache.muse.test.case1.TestThread.run(TestThread.java:60) > > This exception relates to the following code parts in the EPR > implementation: > > ... > Document doc = XmlUtils.EMPTY_DOC; > _xml = XmlUtils.createElement(doc, typeName); > > NodeList children = copy.toXML().getChildNodes(); > int length = children.getLength(); > > for (int n = 0; n < length; ++n) > { > Node next = doc.importNode(children.item(n), true); > _xml.appendChild(next); > } > > try > { > initializeFromXML(); > } > ... > > The reason for the exception is that multiple threads import nodes into > the SHARED document. Later on in initializeFromXML() the different element > nodes within the SHARED document are traversed simulations, which leads to > the threading issue. The usage of ThreadLocal WILL eliminate such errors, > since no SHARED document is used between the different threads to create XML > elements. In fact each thread has its own document that is used for this. > This is shown in the sample thread local. > > 2.) > > java.lang.NullPointerException > at org.apache.xerces.dom.ParentNode.nodeListItem(Unknown Source) > at org.apache.xerces.dom.ParentNode.item(Unknown Source) > at > org.apache.muse.test.case1.TestEndpointReference.<init>(TestEndpointReference.java:187) > at org.apache.muse.test.case1.TestThread.run(TestThread.java:60) > > The second exception has a similar background. In the test case the > initial EPRs are created in the class Test via the > > TestEndpointReference(URI address, QName typeName) > > constructor. This constructor creates the internal XML representation by > using EMPTY_DOC. The original EPR is copied by the following code: > > NodeList children = copy.toXML().getChildNodes(); > int length = children.getLength(); > > for (int n = 0; n < length; ++n) > { > Node next = doc.importNode(children.item(n), true); > _xml.appendChild(next); > } > > The copy.toXML() method simply returns the XML element created with > EMPTY_DOC. Here again multiple thread try to traverse the same node > concurrently which leads to the exception. > > Therefore, in my point of view we have two different problems: > > > 1.) Multiple threads must not use the same target document to import > nodes. > > This means XML elements, that are only used within a request/response > cycle (e.g. for de-/serialization) can use ThreadLocal mechnisms. > It is not necessary to create new documents all the way for this > purpose. > > 2.) XML elements, that have a lifetime longer than a request/response > cycle, must be created by using new (not shared) documents. This I > already > pointed out in my first mail. This is especially true for EPRs, that > are > > > I attached a number of test cases that illustrate my point. > > To Rich: > > >>The default implementation creates a thread for processing the > >>notify request, and then immediately releases the thread that called > it. > > You are right: in this special case the objects need to be copied > by using a separate document, since here the message objects leave the > request/response cycle. This has to be taken into account. > > Finally, the usage of createDocument() compared to the solution I > presented adds a performance overhead of more than 50%. This can simply be > verified > with the tests I attached. However, I admit that my solution requires more > attention by the programmers than simply replacing EMPTY_DOC, but I think > it is worth. > > Interestingly, I still found that sometimes exceptions will occur, even > when using new documents for every XML operation. This is really rare, but in > my opinion this results from the “still†shared usage of DOM > objects within the EPR (the _xml element). Therefore, concurrent read access > to this instance variable can still occour. To solve the problem with the > EPR completely, this instance variable should perhaps be removed from the > EPR implementation. > > Regards, > Oliver > > p.s. unfortunatelly I could not attach the test files, since this is > rejected by the mailer deamon. However, I could provide the test in the JIRA. > -- > Psssst! Schon vom neuen GMX MultiMessenger gehört? > Der kanns mit allen: http://www.gmx.net/de/go/multimessenger > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > -- GMX FreeMail: 1 GB Postfach, 5 E-Mail-Adressen, 10 Free SMS. Alle Infos und kostenlose Anmeldung: http://www.gmx.net/de/go/freemail --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
