Conversation
|
OK, this fails on Linux because the file entries are removed earlier than expected by the test. However, |
| try (InputStream in = backend.getRecord(getIdentifier()).getStream()) { | ||
| copyInputStreamToFile(in, tmpFile); | ||
| return new LazyFileInputStream(tmpFile); | ||
| return new FileInputStream(tmpFile); |
There was a problem hiding this comment.
You might have better luck returning an InputStream that deletes the tmpFile on InputStream#close(). However, that requires all users of the API to actually close the stream.
Of course this could be combined with the TransientFileFactory as a safeguard. I.e. the TransientFileFactory would only clean up after non-conforming users.
Out of curiosity, why do you want to get rid of the TransientFileFactory? Are there problems with it?
There was a problem hiding this comment.
Won't this cause issues, since we are deleting the file before returning the FileInputStream?
cc @amit-jain
There was a problem hiding this comment.
Also, this won't work well in Windows:
- On Windows, you cannot delete a file that is open by any process.
- On Unix-like systems, you can delete an open file, and the file's data remains accessible to processes that have it open until all handles are closed.
So basically, on Windows, we would be having garbage files under tmp folders since we are opening a Stream before calling delete.
See : https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea
There was a problem hiding this comment.
Created a new to check this on MacOS:
private Object[] createTempFileAndReturnStream() throws Exception {
File tempFile = File.createTempFile("test", ".txt");
System.out.println(tempFile.getAbsolutePath());
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
fos.write("hello world".getBytes());
}
FileInputStream fis = new FileInputStream(tempFile);
// Delete the file immediately after opening the stream
tempFile.delete();
return new Object[]{fis, tempFile};
}
@Test
public void testWaitForBucketNotFound() throws Exception {
FileInputStream fis = null;
String name = null;
try {
Object[] tempFileAndReturnStream = createTempFileAndReturnStream();
fis = (FileInputStream) tempFileAndReturnStream[0];
name = tempFileAndReturnStream[1].toString();
byte[] buf = new byte[11];
int read = fis.read(buf);
Assert.assertEquals(11, read);
Assert.assertEquals("hello world", new String(buf));
System.out.println(Path.of(name));
Assert.assertFalse(Files.exists(Path.of(name)));
} finally {
if (fis != null) {
fis.close();
}
Assert.assertFalse(Files.exists(Path.of(name)));
}
}
On Mac, it is working fine, but I couldn't test on Windows since I don't have one.
@Joscorbe could you please try the above test on Windows if possible?
There was a problem hiding this comment.
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.357 s <<< FAILURE! -- in org.apache.jackrabbit.oak.plugins.blob.TransientFileFactoryTest
[ERROR] org.apache.jackrabbit.oak.plugins.blob.TransientFileFactoryTest.testWaitForBucketNotFound -- Time elapsed: 0.320 s <<< FAILURE!
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:87)
at org.junit.Assert.assertTrue(Assert.java:42)
at org.junit.Assert.assertFalse(Assert.java:65)
at org.junit.Assert.assertFalse(Assert.java:75)
at org.apache.jackrabbit.oak.plugins.blob.TransientFileFactoryTest.testWaitForBucketNotFound(TransientFileFactoryTest.java:67)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] TransientFileFactoryTest.testWaitForBucketNotFound:67
[INFO]
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
No description provided.