Hi All, Hope all is well. During our recent load tests I've come across a thread-related bug in the ProgramGenerator implementation. The symptoms are similar to the sitemap recompilation issue we faced last week. If 2 simultaneous requests ask for the same xsp resource, which is not compiled, or has changed, etc, then the that resource is created and loaded twice. If the loading of the class occurs while the second request is (re)compiling it, then very strange things happen.. :-) I've been able to reproduce this easily in our test environment, and have attached a patch (using the Carsten method (TM) :-) ) which fixes the problem. Hope it's all ok. Cheers, Marcus -- ..... ,,$$$$$$$$$, Marcus Crafter ;$' '$$$$: Computer Systems Engineer $: $$$$: Open Software Associates GmbH $ o_)$$$: 82-84 Mainzer Landstrasse ;$, _/\ &&:' 60327 Frankfurt Germany ' /( &&& \_&&&&' Email : [EMAIL PROTECTED] &&&&. Business Hours : +49 69 9757 200 &&&&&&&:
Index: src/org/apache/cocoon/components/language/generator/ProgramGeneratorImpl.java =================================================================== RCS file: /home/cvspublic/xml-cocoon2/src/org/apache/cocoon/components/language/generator/ProgramGeneratorImpl.java,v retrieving revision 1.5.2.14 diff -u -r1.5.2.14 ProgramGeneratorImpl.java --- src/org/apache/cocoon/components/language/generator/ProgramGeneratorImpl.java 2001/08/22 03:57:58 1.5.2.14 +++ src/org/apache/cocoon/components/language/generator/ProgramGeneratorImpl.java + 2001/08/29 15:47:06 @@ -101,8 +101,9 @@ } /** - * Set the global component manager. This metod also sets the - * <code>ComponentSelector</code> used as language factory for both markup and programming languages. + * Set the global component manager. This method also sets the + * <code>ComponentSelector</code> used as language factory for both markup + * and programming languages. * @param manager The global component manager */ public void compose(ComponentManager manager) throws ComponentException { @@ -171,7 +172,7 @@ try { programInstance = (CompiledComponent) select(normalizedName); } catch (Exception e) { - getLogger().debug("The instance was not accessible, creating it now."); + getLogger().debug("The instance was not accessible from the internal +cache. Proceeding."); } if ((programInstance == null) && this.preload) { @@ -187,32 +188,11 @@ } if (programInstance == null) { - MarkupLanguage markupLanguage = null; - ProgrammingLanguage programmingLanguage = null; - try { - // Get markup and programming languages - markupLanguage = (MarkupLanguage)this.markupSelector.select(markupLanguageName); - programmingLanguage = (ProgrammingLanguage)this.languageSelector.select(programmingLanguageName); - programmingLanguage.setLanguageName(programmingLanguageName); - program = this.generateResource(newManager, fileName, normalizedName, markupLanguage, programmingLanguage, resolver); - } catch (LanguageException le) { - getLogger().debug("Language Exception", le); - throw new ProcessingException("Language Exception", le); - } finally { - if (this.markupSelector != null) { - this.markupSelector.release(markupLanguage); - } - - if (this.languageSelector != null) { - this.languageSelector.release(programmingLanguage); - } - } - - try { - programInstance = (CompiledComponent) select(normalizedName); - } catch (Exception cme) { - getLogger().debug("Can't load ServerPage", cme); - } + programInstance = + this.createResource( + newManager, fileName, normalizedName, + markupLanguageName, programmingLanguageName, resolver + ); } if (this.autoReload == false) { @@ -241,30 +221,80 @@ if (programInstance == null) { if (program == null) { - MarkupLanguage markupLanguage = null; - ProgrammingLanguage programmingLanguage = null; - try { - // Get markup and programming languages - markupLanguage = (MarkupLanguage)this.markupSelector.select(markupLanguageName); - programmingLanguage = (ProgrammingLanguage)this.languageSelector.select(programmingLanguageName); - programmingLanguage.setLanguageName(programmingLanguageName); - program = this.generateResource(newManager, fileName, normalizedName, markupLanguage, programmingLanguage, resolver); - } catch (LanguageException le) { - getLogger().debug("Language Exception", le); - throw new ProcessingException("Language Exception", le); - } finally { - this.markupSelector.release(markupLanguage); - this.languageSelector.release(programmingLanguage); - } - } - // Instantiate - programInstance = (CompiledComponent) select(normalizedName); + programInstance = + this.createResource( + newManager, fileName, normalizedName, + markupLanguageName, programmingLanguageName, + resolver + ); + } else + programInstance = (CompiledComponent) select(normalizedName); } return programInstance; } finally { source.recycle(); } + } + + /** + * Helper method to create resources in a threadsafe manner. + */ + private CompiledComponent createResource( + ComponentManager newManager, + String fileName, + String normalizedName, + String markupLanguageName, + String programmingLanguageName, + SourceResolver resolver + ) + throws Exception { + + CompiledComponent programInstance = null; + MarkupLanguage markupLanguage = null; + ProgrammingLanguage programmingLanguage = null; + Class program = null; + + // prevent 2 requests from generating this resource simultaneously + synchronized (this) { + try { + programInstance = (CompiledComponent) select(normalizedName); + } catch (Exception e) { + + getLogger().debug( + "Creating resource " + + normalizedName.replace(File.separatorChar, '.') + + ", using generator " + this + ); + + try { + // Get markup and programming languages + markupLanguage = +(MarkupLanguage)this.markupSelector.select(markupLanguageName); + programmingLanguage = +(ProgrammingLanguage)this.languageSelector.select(programmingLanguageName); + programmingLanguage.setLanguageName(programmingLanguageName); + program = this.generateResource(newManager, fileName, +normalizedName, markupLanguage, programmingLanguage, resolver); + } catch (LanguageException le) { + getLogger().debug("Language Exception", le); + throw new ProcessingException("Language Exception", le); + } finally { + if (this.markupSelector != null) { + this.markupSelector.release(markupLanguage); + } + + if (this.languageSelector != null) { + this.languageSelector.release(programmingLanguage); + } + } + + try { + programInstance = (CompiledComponent) select(normalizedName); + } catch (Exception cme) { + getLogger().debug("Can't load ServerPage", cme); + } + } + } + + return programInstance; } private Class generateResource(ComponentManager newManager, Index: src/org/apache/cocoon/components/language/programming/java/JavaLanguage.java =================================================================== RCS file: /home/cvspublic/xml-cocoon2/src/org/apache/cocoon/components/language/programming/java/JavaLanguage.java,v retrieving revision 1.2.2.4 diff -u -r1.2.2.4 JavaLanguage.java --- src/org/apache/cocoon/components/language/programming/java/JavaLanguage.java 2001/08/21 18:00:01 1.2.2.4 +++ src/org/apache/cocoon/components/language/programming/java/JavaLanguage.java + 2001/08/29 15:47:06 @@ -149,11 +149,10 @@ String pathname = baseDirectory.getCanonicalPath() + File.separator + name.substring(0, pos).replace(File.separatorChar, '/'); + String filename_abs = + pathname + File.separator + filename + "." + this.getSourceExtension(); - compiler.setFile( - pathname + File.separator + - filename + "." + this.getSourceExtension() - ); + compiler.setFile(filename_abs); compiler.setSource(pathname); @@ -179,6 +178,8 @@ if (encoding != null) { compiler.setEncoding(encoding); } + + getLogger().debug("Compiling " + filename_abs); if (!compiler.compile()) { StringBuffer message = new StringBuffer("Error compiling ");
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]