[jboss-dev-forums] [Design of POJO Server] - VFS caching is broken
adrian@jboss.org
do-not-reply at jboss.com
Mon Dec 10 13:11:58 EST 2007
The VFS is using getLastModified() to determine whether
the cache is valid. This is a broken check on Unix because deleting
and replacing a file doesn't cause it to see the new file.
Instead the file descriptor of the deleted file still exists in an unhooked state
(i.e. not visible in the directory), until all references are released.
Here's a test that shows the problem
(basically doing what UndeployBrokenPackageUnitTestCase is doing).
| import java.io.File;
| import java.io.InputStream;
| import java.io.InputStreamReader;
| import java.net.URL;
|
| import org.jboss.util.file.Files;
| import org.jboss.virtual.VFS;
| import org.jboss.virtual.VirtualFile;
|
| public class Test
| {
| public static void main(String[] args) throws Exception
| {
| String testPackage = "ejbredeploy.jar";
| String temp = System.getProperty("java.io.tmpdir");
| File tempFile = new File(temp);
| URL tempURL = tempFile.toURL();
| File thejar = new File(tempFile, "ejbredeploy.jar");
| File badjar = new File(tempFile, "ejbredeploy-bad.jar");
| File goodjar = new File(tempFile, "ejbredeploy-good.jar");
|
|
| thejar.delete();
| Files.copy(badjar, thejar);
| VirtualFile child1 = printEjbJarXml(tempURL);
| System.out.println("child1 " + child1.getLastModified());
|
| Thread.sleep(1000);
|
| thejar.delete();
| Files.copy(goodjar, thejar);
| printEjbJarXml(tempURL);
| VirtualFile child2 = printEjbJarXml(tempURL);
|
| System.out.println("child1 " + child1.getLastModified());
| System.out.println("child2 " + child2.getLastModified());
| }
|
| public static VirtualFile printEjbJarXml(URL tempURL) throws Exception
| {
| VirtualFile file = VFS.getRoot(tempURL);
| VirtualFile child = file.findChild("ejbredeploy.jar/META-INF/ejb-jar.xml");
| InputStream is = child.openStream();
| InputStreamReader reader = new InputStreamReader(is);
| char[] buffer = new char[1024];
| int read = reader.read(buffer, 0, 1024);
| while (read >= 0)
| {
| for (int i = 0; i < read; ++i)
| System.out.print(buffer);
| read = reader.read(buffer, 0, 1024);
| }
| System.out.println();
|
| return child;
| }
| }
|
To run it copy ejbredeploy-good.jar and ejbredeploiy-bad.jar into your temp directory.
The output of the tests shows it does not see the replaced file
and the last modified doesn't change
so it must be holding onto the old file and never looking at the new file:
| <?xml version="1.0" encoding="UTF-8"?>
| <!DOCTYPE ejb-jar
| PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
| "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
|
| <ejb-jar>
| <description>An invalid single entity bean DD</description>
| <enterprise-beans>
| <entity>
| <description>EntityA</description>
| <ejb-name>EntityA</ejb-name>
|
| <home>org.jboss.test.jmx.interfaces.EntityAHome</home>
| <remote>org.jboss.test.jmx.interfaces.EntityA</remote>
|
| <ejb-class>org.jboss.test.jmx.ejb.EntityABean</ejb-class>
| <persistence-type>Container</persistence-type>
| <prim-key-class>java.lang.Integer</prim-key-class>
| <!-- Commenting these fields will make the deployment fail
| <reentrant>False</reentrant>
| <cmp-version>2.x</cmp-version>
| <abstract-schema-name>EntityA</abstract-schema-name>
| <cmp-field >
| <field-name>id</field-name>
| </cmp-field>
| <cmp-field>
| <field-name>value</field-name>
| </cmp-field>
| <primkey-field>id</primkey-field>
| -->
|
| </entity>
| </enterprise-beans>
|
| </ejb-jar>
|
| child1 1194256772000
| <?xml version="1.0" encoding="UTF-8"?>
| <!DOCTYPE ejb-jar
| PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
| "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
|
| <ejb-jar>
| <description>A valid single entity bean DD</description>
| <enterprise-beans>
| <entity>
| <description>EntityA</description>
| <ejb-name>EntityA</ejb-name>
|
| <home>org.jboss.test.jmx.interfaces.EntityAHome</home>
| <remote>org.jboss.test.jmx.interfaces.EntityA</remote>
|
| <ejb-class>org.jboss.test.jmx.ejb.EntityABean</ejb-class>
| <persistence-type>Container</persistence-type>
| <prim-key-class>java.lang.Integer</prim-key-class>
| <reentrant>False</reentrant>
| <cmp-version>2.x</cmp-version>
| <abstract-schema-name>EntityA</abstract-schema-name>
| <cmp-field >
| <field-name>id</field-name>
| </cmp-field>
| <cmp-field>
| <field-name>value</field-name>
| </cmp-field>
| <primkey-field>id</primkey-field>
|
| </entity>
| </enterprise-beans>
|
| </ejb-jar>
|
| <?xml version="1.0" encoding="UTF-8"?>
| <!DOCTYPE ejb-jar
| PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
| "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
|
| <ejb-jar>
| <description>A valid single entity bean DD</description>
| <enterprise-beans>
| <entity>
| <description>EntityA</description>
| <ejb-name>EntityA</ejb-name>
|
| <home>org.jboss.test.jmx.interfaces.EntityAHome</home>
| <remote>org.jboss.test.jmx.interfaces.EntityA</remote>
|
| <ejb-class>org.jboss.test.jmx.ejb.EntityABean</ejb-class>
| <persistence-type>Container</persistence-type>
| <prim-key-class>java.lang.Integer</prim-key-class>
| <reentrant>False</reentrant>
| <cmp-version>2.x</cmp-version>
| <abstract-schema-name>EntityA</abstract-schema-name>
| <cmp-field >
| <field-name>id</field-name>
| </cmp-field>
| <cmp-field>
| <field-name>value</field-name>
| </cmp-field>
| <primkey-field>id</primkey-field>
|
| </entity>
| </enterprise-beans>
|
| </ejb-jar>
|
| child1 1194256772000
| child2 1194256772000
|
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4111720#4111720
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4111720
More information about the jboss-dev-forums
mailing list