You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Joerg Schaible (JIRA)" <ji...@apache.org> on 2007/08/09 17:07:42 UTC

[jira] Created: (VFS-172) Cache of SFTP after move completely out of sync.

Cache of SFTP after move completely out of sync.
------------------------------------------------

                 Key: VFS-172
                 URL: https://issues.apache.org/jira/browse/VFS-172
             Project: Commons VFS
          Issue Type: Bug
    Affects Versions: 1.0
            Reporter: Joerg Schaible
            Priority: Critical


Simple test method. See all the bogus cases at the end:

{code:java}
	public void testObjectsAfterMoveOfParentDoNotExistWithSFTP() throws IOException
	{
		final FileSystemOptions fsOptions = new FileSystemOptions();
		final FileSystemManager fsManager = VFS.getManager();
		final FileObject root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
		if (!root.exists()) {
			root.createFolder();
		}

		assertTrue(root.exists());

		final FileObject target = root.resolveFile("target");
		if (!target.exists()) {
			target.createFolder();
		}

		assertTrue(target.exists());

		final FileObject work = root.resolveFile("work");
		if (!work.exists()) {
			work.createFolder();
		}

		assertTrue(work.exists());

		FileObject inWork = work.resolveFile("inWork");
		if (!inWork.exists()) {
			inWork.createFolder();
		}

		assertTrue(inWork.exists());

		final FileObject ready = target.resolveFile("ready-" + System.currentTimeMillis());
		assertFalse(ready.exists());

		work.moveTo(ready);
		assertTrue(ready.exists());
		assertFalse(work.exists());

		try {
			assertFalse(inWork.exists());
			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
		} catch (final AssertionFailedError e) {
			// <sigh>
		}

		try {
			inWork.refresh();
			assertFalse(inWork.exists());
			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
		} catch (final AssertionFailedError e) {
			// <sigh>
		}

		try {
			assertFalse(work.resolveFile("inWork").exists());
			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
		} catch (final AssertionFailedError e) {
			// <sigh>
		}

		try {
			work.refresh();
			assertFalse(work.resolveFile("inWork").exists());
			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
		} catch (final AssertionFailedError e) {
			// <sigh>
		}
		
		// it even possible to write into a file of the non-existing folder ...
		FileObject file = inWork.resolveFile("test.txt");
		OutputStream out = file.getContent().getOutputStream();
		out.write("Foo".getBytes());
		try {
			out.close();
		} catch(IOException e) {
			// ignore this
		}		
		assertTrue(file.exists());

		// force update of references
		file = null;
		out = null;
		inWork = null;
		System.gc();
		System.gc();
		// ... aaaaahhhh ... something changed
		assertFalse(work.resolveFile("inWork").exists());
	}
{code}

There's not a single possibility to tell VFS that the FileObject is bogus and even worse, you can write into non-existing files of a non-existing folder without getting an Exception ...

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (VFS-172) Cache of SFTP after move completely out of sync.

Posted by "Joerg Schaible (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/VFS-172?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Joerg Schaible updated VFS-172:
-------------------------------

    Attachment: VFS-172.diff

After some debugging I realized that the SftFileObject will never refresh itself. Main cause is that - even if it is detached - it keeps it's attribs. Unfortunately the implementation assumes that it is a real file as long as the attribs are available. My patch resets now the attribs in doDispatch. This solves the problem in the following test case (the caching strategy forces a refresh calling resolveFile):

{code:java}
	public void testObjectsAfterMoveOfParentDoNotExistWithSFTP() throws IOException
	{
		final FileSystemOptions fsOptions = new FileSystemOptions();
		StandardFileSystemManager fsManager = new StandardFileSystemManager();
		fsManager.init();
		FileObject root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
		if (!root.exists()) {
			root.createFolder();
		}

		assertTrue(root.exists());

		final FileObject target = root.resolveFile("target");
		if (!target.exists()) {
			target.createFolder();
		}

		assertTrue(target.exists());

		FileObject work = root.resolveFile("work");
		if (!work.exists()) {
			work.createFolder();
		}

		assertTrue(work.exists());

		FileObject inWork = work.resolveFile("inWork");
		if (!inWork.exists()) {
			inWork.createFolder();
		}

		assertTrue(inWork.exists());

		final FileObject ready = target.resolveFile("ready-" + System.currentTimeMillis());
		assertFalse(ready.exists());

		work.moveTo(ready);
		assertTrue(ready.exists());
		assertFalse(work.exists());
		// resolve forces internal refresh
		assertFalse(work.resolveFile("inWork").exists());
		assertFalse(inWork.exists());
	}
{code}

However, I was not able to run any of the unit tests, they are not found with M2. So I have no idea if the patch has side effects.

> Cache of SFTP after move completely out of sync.
> ------------------------------------------------
>
>                 Key: VFS-172
>                 URL: https://issues.apache.org/jira/browse/VFS-172
>             Project: Commons VFS
>          Issue Type: Bug
>    Affects Versions: 1.0
>            Reporter: Joerg Schaible
>            Priority: Critical
>         Attachments: VFS-172.diff
>
>
> Simple test method. See all the bogus cases at the end:
> {code:java}
> 	public void testObjectsAfterMoveOfParentDoNotExistWithSFTP() throws IOException
> 	{
> 		final FileSystemOptions fsOptions = new FileSystemOptions();
> 		final FileSystemManager fsManager = VFS.getManager();
> 		final FileObject root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
> 		if (!root.exists()) {
> 			root.createFolder();
> 		}
> 		assertTrue(root.exists());
> 		final FileObject target = root.resolveFile("target");
> 		if (!target.exists()) {
> 			target.createFolder();
> 		}
> 		assertTrue(target.exists());
> 		final FileObject work = root.resolveFile("work");
> 		if (!work.exists()) {
> 			work.createFolder();
> 		}
> 		assertTrue(work.exists());
> 		FileObject inWork = work.resolveFile("inWork");
> 		if (!inWork.exists()) {
> 			inWork.createFolder();
> 		}
> 		assertTrue(inWork.exists());
> 		final FileObject ready = target.resolveFile("ready-" + System.currentTimeMillis());
> 		assertFalse(ready.exists());
> 		work.moveTo(ready);
> 		assertTrue(ready.exists());
> 		assertFalse(work.exists());
> 		try {
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			inWork.refresh();
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			work.refresh();
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		
> 		// it even possible to write into a file of the non-existing folder ...
> 		FileObject file = inWork.resolveFile("test.txt");
> 		OutputStream out = file.getContent().getOutputStream();
> 		out.write("Foo".getBytes());
> 		try {
> 			out.close();
> 		} catch(IOException e) {
> 			// ignore this
> 		}		
> 		assertTrue(file.exists());
> 		// force update of references
> 		file = null;
> 		out = null;
> 		inWork = null;
> 		System.gc();
> 		System.gc();
> 		// ... aaaaahhhh ... something changed
> 		assertFalse(work.resolveFile("inWork").exists());
> 	}
> {code}
> There's not a single possibility to tell VFS that the FileObject is bogus and even worse, you can write into non-existing files of a non-existing folder without getting an Exception ...

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (VFS-172) Cache of SFTP after move completely out of sync.

Posted by "Mario Ivankovits (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/VFS-172?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Mario Ivankovits resolved VFS-172.
----------------------------------

       Resolution: Fixed
    Fix Version/s: 1.1
         Assignee: Mario Ivankovits

Applied - Thanks for the patch!
Also implemented the refresh() method now to make the CachePolicy work with sftp too.

Test case still works, so it looks good to me.


> Cache of SFTP after move completely out of sync.
> ------------------------------------------------
>
>                 Key: VFS-172
>                 URL: https://issues.apache.org/jira/browse/VFS-172
>             Project: Commons VFS
>          Issue Type: Bug
>    Affects Versions: 1.0
>            Reporter: Joerg Schaible
>            Assignee: Mario Ivankovits
>            Priority: Critical
>             Fix For: 1.1
>
>         Attachments: VFS-172.diff
>
>
> Simple test method. See all the bogus cases at the end:
> {code:java}
> 	public void testObjectsAfterMoveOfParentDoNotExistWithSFTP() throws IOException
> 	{
> 		final FileSystemOptions fsOptions = new FileSystemOptions();
> 		final FileSystemManager fsManager = VFS.getManager();
> 		final FileObject root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
> 		if (!root.exists()) {
> 			root.createFolder();
> 		}
> 		assertTrue(root.exists());
> 		final FileObject target = root.resolveFile("target");
> 		if (!target.exists()) {
> 			target.createFolder();
> 		}
> 		assertTrue(target.exists());
> 		final FileObject work = root.resolveFile("work");
> 		if (!work.exists()) {
> 			work.createFolder();
> 		}
> 		assertTrue(work.exists());
> 		FileObject inWork = work.resolveFile("inWork");
> 		if (!inWork.exists()) {
> 			inWork.createFolder();
> 		}
> 		assertTrue(inWork.exists());
> 		final FileObject ready = target.resolveFile("ready-" + System.currentTimeMillis());
> 		assertFalse(ready.exists());
> 		work.moveTo(ready);
> 		assertTrue(ready.exists());
> 		assertFalse(work.exists());
> 		try {
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			inWork.refresh();
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			work.refresh();
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		
> 		// it even possible to write into a file of the non-existing folder ...
> 		FileObject file = inWork.resolveFile("test.txt");
> 		OutputStream out = file.getContent().getOutputStream();
> 		out.write("Foo".getBytes());
> 		try {
> 			out.close();
> 		} catch(IOException e) {
> 			// ignore this
> 		}		
> 		assertTrue(file.exists());
> 		// force update of references
> 		file = null;
> 		out = null;
> 		inWork = null;
> 		System.gc();
> 		System.gc();
> 		// ... aaaaahhhh ... something changed
> 		assertFalse(work.resolveFile("inWork").exists());
> 	}
> {code}
> There's not a single possibility to tell VFS that the FileObject is bogus and even worse, you can write into non-existing files of a non-existing folder without getting an Exception ...

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (VFS-172) Cache of SFTP after move completely out of sync.

Posted by "Joerg Schaible (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/VFS-172?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12518921 ] 

Joerg Schaible commented on VFS-172:
------------------------------------

It seems that the main problem is not the VFS code itself, but the usage of the jCraft library. Even after the following sequence the assert fails:

{code:java}
		work.moveTo(ready);
		assertTrue(ready.exists());
		assertFalse(work.exists());
		
		fsManager.close();
		fsManager = new StandardFileSystemManager();
		fsManager.init();
		root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
		work = root.resolveFile("work");

		assertFalse(work.resolveFile("inWork").exists());
{code}

I tried this with com.jcraft:jsch-0.1.23 and the current version com.jcraft:jsch-0.1.31. It seems that jsch keeps also a cache that is not reseted.

> Cache of SFTP after move completely out of sync.
> ------------------------------------------------
>
>                 Key: VFS-172
>                 URL: https://issues.apache.org/jira/browse/VFS-172
>             Project: Commons VFS
>          Issue Type: Bug
>    Affects Versions: 1.0
>            Reporter: Joerg Schaible
>            Priority: Critical
>
> Simple test method. See all the bogus cases at the end:
> {code:java}
> 	public void testObjectsAfterMoveOfParentDoNotExistWithSFTP() throws IOException
> 	{
> 		final FileSystemOptions fsOptions = new FileSystemOptions();
> 		final FileSystemManager fsManager = VFS.getManager();
> 		final FileObject root = fsManager.resolveFile(SFTP_BASE_URL + "junit", fsOptions);
> 		if (!root.exists()) {
> 			root.createFolder();
> 		}
> 		assertTrue(root.exists());
> 		final FileObject target = root.resolveFile("target");
> 		if (!target.exists()) {
> 			target.createFolder();
> 		}
> 		assertTrue(target.exists());
> 		final FileObject work = root.resolveFile("work");
> 		if (!work.exists()) {
> 			work.createFolder();
> 		}
> 		assertTrue(work.exists());
> 		FileObject inWork = work.resolveFile("inWork");
> 		if (!inWork.exists()) {
> 			inWork.createFolder();
> 		}
> 		assertTrue(inWork.exists());
> 		final FileObject ready = target.resolveFile("ready-" + System.currentTimeMillis());
> 		assertFalse(ready.exists());
> 		work.moveTo(ready);
> 		assertTrue(ready.exists());
> 		assertFalse(work.exists());
> 		try {
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			inWork.refresh();
> 			assertFalse(inWork.exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		try {
> 			work.refresh();
> 			assertFalse(work.resolveFile("inWork").exists());
> 			fail("Thrown " + AssertionFailedError.class.getName() + " expected, because of buggy implementation");
> 		} catch (final AssertionFailedError e) {
> 			// <sigh>
> 		}
> 		
> 		// it even possible to write into a file of the non-existing folder ...
> 		FileObject file = inWork.resolveFile("test.txt");
> 		OutputStream out = file.getContent().getOutputStream();
> 		out.write("Foo".getBytes());
> 		try {
> 			out.close();
> 		} catch(IOException e) {
> 			// ignore this
> 		}		
> 		assertTrue(file.exists());
> 		// force update of references
> 		file = null;
> 		out = null;
> 		inWork = null;
> 		System.gc();
> 		System.gc();
> 		// ... aaaaahhhh ... something changed
> 		assertFalse(work.resolveFile("inWork").exists());
> 	}
> {code}
> There's not a single possibility to tell VFS that the FileObject is bogus and even worse, you can write into non-existing files of a non-existing folder without getting an Exception ...

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.