I have a web application running in cluster mode with a load balancer.
It consists in two tomcats (T1, and T2) addressing only one DB.
T2 is nfs mounted to T1. This is the only dofference between both nodes.
I have a java method generating some files. If the request
runs on T1 there is no problem but if the request is running on node 2
I get an exception as follows:
java.io.IOException: Invalid argument
at java.io.FileOutputStream.close0(Native Method)
at java.io.FileOutputStream.close(FileOutputStream.java:279)
The corresponding code is as follows:
for (int i = 0; i < dataFileList.size(); i++) {
outputFileName = outputFolder + fileNameList.get(i);
FileOutputStream fileOut = new FileOutputStream(outputFileName);
fileOut.write(dataFileList.get(i), 0, dataFileList.get(i).length);
fileOut.flush();
fileOut.close();
}
The exception appears at the fileOut.close()
Any hint?
Luis
Setting this line in the .profile resolved the issue:
ulimit –n 2048
How large do dataFileList and fileNameList get? You could be running out of file descriptors. It's odd that it happens on close(), though.
Finally I found the reason.
First I've notices that NOT always this exception comes
at the same point.
Sometimes was a
java.io.IOException: Invalid argument
at java.io.FileOutputStream.close0(Native Method)
at java.io.FileOutputStream.close(FileOutputStream.java:279)
^^^^^
and sometimes was
java.io.IOException: Invalid argument
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:260)
Therefore the problem is NOT a java problem. Not even a NFS problem.
The problem is the underlying File System type which is an DRBD
file system.
Testing at a shell to write across the nodes works if one is writing a small
file. I.e:
at the nfs mounted node
cd /tmp
date > /shared/path-to-some-not-mounted-dir/today
will work
but
cat myBigFile > /shared/path-to-some-not-mounted-dir/today
will deliver the following error
cat: write error: Invalid argument
Therefore the solution is to use other type of file system, gfs for example.
Related
I am creating a file like so
try {
File file = new File(workingDir, obj.getName() + ".xls");
outputStream = new FileOutputStream(file);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
And I am getting
java.io.FileNotFoundException: ..\a\relative\path\obj_name.xls (The parameter is incorrect)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
What does "the parameter is incorrect" mean? The pathname I validated exists; shouldn't it just create the file name? This is on a windows machine. The code works without this error on unix based systems.
Update
Verified that the file exists that the output stream is attempting to write to. Also verified that the file is writable. After much fussing, I removed the actual path and just passed in the file name (not desired) and that works. So the issue has something to do with the path. Do I need to escape the characters in the path?
This looks like a reported bug on Windows machines.
Under normal situations, something like a path that has a colon (:) in it which does not refer to a drive letter would cause this message.
It appears to be an issue with the path you're using. Try using file.getPath() before you open it to debug what is going on with your path.
File file = new File(workingDir, obj.getName() + ".xls");
System.out.println("Path="+file.getPath());
outputStream = new FileOutputStream(file);
If your "workingDir" is a relative path, then are you sure you are on the correct "current directory" when you moved your app from unix to windows? Maybe, you should check what the current directory of the running application is.
Perhaps the application doesn't have the correct access to write to the file? Is it read-only or otherwise protected?
FileOutputStream.open() is a native method, I would assume any sort of exception message such as "The parameter is incorrect" is coming from the underlying OS.
BTW: the File constructor does not call FileOutputStream.open(), so is the exception not actually coming from the code you posted here?
Maybe it's because of the backslashes in the path? Path too long? File name invalid for this error (special caracters...) ?
I might be totally wrong, but worth a try since it sounds like a OS dependent error.
Make sure the user that runs the JVM process has the right permissions to access that file.
I know this has been probably answered a million times on here but everything I have looked at has not helped me. Here is my code:
for(File g: f.listFiles()){
for(File h : g.listFiles()){
try{
Scanner s = new Scanner(h);
String timestamp = s.next().split("[?]")[4];
File z = new File(h.getAbsolutePath().split("[.]")[0] + timestamp + h.getAbsolutePath().split("[.]")[1]);
boolean q = h.renameTo(z);
}catch(Exception e){
}
}
}
I have checked to see if File z exists and it doesnt. I have checked if File h exists and it does. I have doublechecked that h is an absolute path. If I print the absolute path of z, I get the correct path. None of the directories in f or files in g are open. The files denoted by h are not open. Could there be some flag set or something on the file where windows is not allowing my program to rename it?
My guess is that you are having a similar problem to one I had here File deletion/moving failing
Try using FileinputStreams for the Scanner
FileInputStream fin = new FileInputStream(h);
fin.open()
Scanner s = new Scanner(fin);
//do work
fin.close()
and closing the stream before renaming
The behavior of renameTo varies from platform to platform. Operations that succeed on one platform may fail on another. For example, on my local development workstation (OS X), everything worked as expected. On a production system (Solaris), renameTo failed consistently. I finally determined that it failed when the files were located on different partitions. Obviously that is not the case here, but it illustrates that the method can behave in unexpected ways.
To get consistent behavior, copy the data to a new file, then delete the original.
I had a almost same issue. Some of rename cases succeeded, some failed. For those failed cases, I found, the source file path and destination file path are not on in same file system. In my cases, the NTFS mounted another file system which the destination file would be moved to. Since the rename function's original purpose simply rename a name, not to move the data of the concerned file. If both source file path and destination file path are in different file system, some version of JVM will fail on certain platforms. Actually, it is a bug in java.io and Solaris has fixed this bug in new versions.
Good Luck!
HappyForever,
I have a partition in Android that's not mounted because it doesn't have a file system, and I need to write a string into it. I tried three different methods, and only the first (from adb) works. I need to do this under program control, which is what the second and third methods do, but both fail. I tried adding system permissions to my app, but that didn't help. Do I need root permission to do this from a program?
First Method -
adb shell "echo test > /cache/command"
adb shell dd if=/cache/command of=/dev/block/mmcblk3p3 bs=4096 seek=1
Second Method -
java.lang.Process p = Runtime.getRuntime().exec(
"dd if=/cache/command of=/dev/block/mmcblk3p3 bs=4096 seek=1");
Third Method -
File fileName = new File("/dev/block/mmcblk3p3");
String cmd = "test";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(cmd.getBytes(), 4096, cmd.length());
fos.flush();
The second method gives no feedback, even though it failed to work. The third method gives the following output:
W/System.err( 1014): java.io.FileNotFoundException:
/dev/block/mmcblk3p3 (Permission denied)
I should warn you about the risks you may have enabling liberal permissions on partitions that should not be accessed by applications. Having said that and assuming you know the risks, what you can do is to change the permissions, if you want to do it permanently you can add
chmod 0666 /dev/block/mmcblk3p3
to init.rc.
There are sections containing other chmod commands where you can put yours.
My guesses were wrong, and had nothing to do with the answer. This question is no longer valid. See my answer. Sorry about this poor question.
Tl;dr Version
Why can't a Java process find a certain file, until another process – the process that created that file – has finished executing. Can this be worked around?
Longer Version
I have an application that needs to restart itself (it just needs to, okay?). The first time, it creates a File and then serializes an object there. This is done with a FileOutputStream/ObjectOutputStream combo, as described below:
private static File serializeBootstrapInfoIntoFile(
final BootstrapInfo info) throws IOException {
final File tempFile = File.createTempFile("BobBootstrapInfo", null);
final FileOutputStream fos = new FileOutputStream(tempFile);
final ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(info);
// just being thorough
oos.flush();
oos.close();
fos.flush();
fos.close();
return tempFile;
}
After this, I create another java process with a System.exec()-call, to which I pass the the absolute path of the returned tempFile as a system property. The other java process should then open the file, and deserialize the containing Object. The first process remains alive until the spawned process exits, since it handles the new one's output/error streams.
The problem is, however, that the second process doesn't seem to find the file, and dies always in a FileNotFoundException during deserialization (I've confirmed this with a file.exists()).
When I check manually afterwards, the file does indeed exist. Also, if I manually run the exact same command line that is passed to the System.exec(), it runs fine. So, I'm guessing the first process somehow manages to hide the file from the new process, or fails to actually write the file to the file system, even the streams are flushed and closed. I also tried with Thread.sleep(10000) on the first thread, to let the IO operations to finish, but that didn't help a bit.
Am I doing something wrong? Or is this a Java thing, or maybe an OSX thing (which I'm running with atm)?
Answers to Comments
I'm running OS X 10.6.3, and the Java version is 1.6.0_20.
The System.exec() arguments are
java
-classpath
/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/bob7168396245507677201.tmp:/Users/wolfie/Documents/workspace/Bob/dist/lib/junit.jar:/Users/wolfie/Documents/workspace/Bob/dist/lib/bob.jar
-Dcache.location="/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4944987280015634213.tmp"
com.github.wolfie.bob.Bob
where each line is an element in a String array. The /var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp-file is the one that was created, and being read by the other thread. The envp and dir arguments are null.
The whole stacktrace is:
Exception in thread "main" com.github.wolfie.bob.BootstrapError: java.io.FileNotFoundException: "/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp" (No such file or directory)
at com.github.wolfie.bob.Bob.getBootstrapInfo(Bob.java:186)
at com.github.wolfie.bob.Bob.run(Bob.java:138)
at com.github.wolfie.bob.Bob.main(Bob.java:95)
Caused by: java.io.FileNotFoundException: "/var/folders/dr/drDlHsguGvq0zF2Jtgn4S++++TI/-Tmp-/BobBootstrapInfo4606780571989099166.tmp" (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at com.github.wolfie.bob.Bob.deserializeBootstrapInfoFromFile(Bob.java:265)
at com.github.wolfie.bob.Bob.getBootstrapInfo(Bob.java:184)
... 2 more
The answer isn't visible from the question: I defined the system property like so:
-Dcache.location="/foo/file.ext"
But the property should've been instead
-Dcache.location=/foo/file.ext
i.e. without the quotes. This, apparently, was ignored when the exact same arguments were passed from the command line, probably because Bash processed them in a different way to the JVM.
Sorry about the poor question.
I am creating a file like so
try {
File file = new File(workingDir, obj.getName() + ".xls");
outputStream = new FileOutputStream(file);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
And I am getting
java.io.FileNotFoundException: ..\a\relative\path\obj_name.xls (The parameter is incorrect)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
What does "the parameter is incorrect" mean? The pathname I validated exists; shouldn't it just create the file name? This is on a windows machine. The code works without this error on unix based systems.
Update
Verified that the file exists that the output stream is attempting to write to. Also verified that the file is writable. After much fussing, I removed the actual path and just passed in the file name (not desired) and that works. So the issue has something to do with the path. Do I need to escape the characters in the path?
This looks like a reported bug on Windows machines.
Under normal situations, something like a path that has a colon (:) in it which does not refer to a drive letter would cause this message.
It appears to be an issue with the path you're using. Try using file.getPath() before you open it to debug what is going on with your path.
File file = new File(workingDir, obj.getName() + ".xls");
System.out.println("Path="+file.getPath());
outputStream = new FileOutputStream(file);
If your "workingDir" is a relative path, then are you sure you are on the correct "current directory" when you moved your app from unix to windows? Maybe, you should check what the current directory of the running application is.
Perhaps the application doesn't have the correct access to write to the file? Is it read-only or otherwise protected?
FileOutputStream.open() is a native method, I would assume any sort of exception message such as "The parameter is incorrect" is coming from the underlying OS.
BTW: the File constructor does not call FileOutputStream.open(), so is the exception not actually coming from the code you posted here?
Maybe it's because of the backslashes in the path? Path too long? File name invalid for this error (special caracters...) ?
I might be totally wrong, but worth a try since it sounds like a OS dependent error.
Make sure the user that runs the JVM process has the right permissions to access that file.