***************
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.xadisk.bridge.proxies.interfaces.Session;
import org.xadisk.bridge.proxies.interfaces.XAFileOutputStream;
import org.xadisk.bridge.proxies.interfaces.XAFileSystem;
import org.xadisk.bridge.proxies.interfaces.XAFileSystemProxy;
import org.xadisk.filesystem.exceptions.ClosedStreamException;
import org.xadisk.filesystem.exceptions.FileAlreadyExistsException;
import org.xadisk.filesystem.exceptions.FileNotExistsException;
import org.xadisk.filesystem.exceptions.FileUnderUseException;
import
org.xadisk.filesystem.exceptions.InsufficientPermissionOnFileException;
import org.xadisk.filesystem.exceptions.LockingFailedException;
import
org.xadisk.filesystem.exceptions.NoTransactionAssociatedException;
import
org.xadisk.filesystem.standalone.StandaloneFileSystemConfiguration;
/**
* Example implementation of XADisk with a couple of transactions.
*
* @author kbonnette
*
*/
public class Example {
// needs to be an absolute path
// see http://java.net/jira/browse/XADISK-94
String xadiskSystemDirectory = "C:\\xadisk";
XAFileSystem xafs = null;
/**
* Initializes the XADisk server.
*/
public void setUpXADisk() {
System.out.println("setup start");
StandaloneFileSystemConfiguration configuration = new
StandaloneFileSystemConfiguration(
xadiskSystemDirectory, "id-1");
// the line below resolves some errors that XADisk has with absolute
// paths and relative paths.
// directories are still written, but with java.io.File.mkdir()
instead
// of the XADisk method.
// see http://java.net/jira/browse/XADISK-95
configuration.setSynchronizeDirectoryChanges(false);
xafs = XAFileSystemProxy.bootNativeXAFileSystem(configuration);
try {
xafs.waitForBootup(-1);
System.out.println("setup end");
} catch (InterruptedException e) {
e.printStackTrace();
System.err.println("Unable to boot XADisk, killing process");
System.exit(1);
}
}
/**
* Shuts down the running XADisk server.
*/
public void shutDown() {
System.out.println("shutdown start");
if (xafs != null) {
try {
xafs.shutdown();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
System.out.println("shutdown end");
}
/**
* regular file io with UNC paths
*/
private void example2a() {
System.out.println("Example 2a ---------------------------------");
try {
File directory = new File("\\\\phfileserver\\development\\xadisk");
if (!directory.exists()) {
if (!directory.mkdir()) {
System.err.println("Could not create directory");
return;
}
}
System.out.println("Writing first");
File first = new File(
"\\\\phfileserver\\development\\xadisk\\first.txt");
if (!first.exists()) {
if (!first.createNewFile()) {
System.err.println("Could not create first");
return;
}
}
// populate text file
System.out.println("populating first");
FileOutputStream xos;
xos = new FileOutputStream(first, false);
xos.write("This is my file\nThis is my text\nThis is for writing
\nReading comes next"
.getBytes());
xos.flush();
xos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Example with UNC paths
*/
public void example2() {
System.out.println("Example 2 ---------------------------------");
Session session;
try {
session = xafs.createSessionForLocalTransaction();
// create directory
System.out.println("Writing Directory");
File directory = new File("\\\\phfileserver\\development\\xadisk");
if (!session.fileExistsAndIsDirectory(directory)) {
session.createFile(directory, true);
}
// create text file
System.out.println("Writing first");
File first = new File(
"\\\\phfileserver\\development\\xadisk\\first.txt");
if (!session.fileExists(first)) {
session.createFile(first, false);
}
// populate text file
System.out.println("populating first");
XAFileOutputStream xos = session.createXAFileOutputStream(first,
false);
xos.write("This is my file\nThis is my text\nThis is for writing
\nReading comes next"
.getBytes());
xos.flush();
xos.close();
System.out.println("precommit");
session.commit();
System.out.println("postcommit");
} catch (NoTransactionAssociatedException e) {
e.printStackTrace();
} catch (FileAlreadyExistsException e) {
e.printStackTrace();
} catch (FileNotExistsException e) {
e.printStackTrace();
} catch (InsufficientPermissionOnFileException e) {
e.printStackTrace();
} catch (LockingFailedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (FileUnderUseException e) {
e.printStackTrace();
} catch (ClosedStreamException e) {
e.printStackTrace();
}
}
/**
* Main method. sets up server, runs local, remote, and both
examples, then
* shuts down server.
*
* @param args
*/
public static void main(String[] args) {
Example example = new Example();
example.setUpXADisk();
example.example2a();
example.example2();
example.shutDown();
}
}
***************************************
setup start
setup end
Example 2a ---------------------------------
Writing first
populating first
Example 2 ---------------------------------
Writing Directory
shutdown start
shutdown end
org.xadisk.filesystem.exceptions.InsufficientPermissionOnFileException:
Permission of type [READ_DIRECTORY] is needed over the file/directory
with path [\\phfileserver\development] for the i/o operation to
succeed.
at
org.xadisk.filesystem.NativeSession.checkPermission(NativeSession.java:
1018)
at
org.xadisk.filesystem.NativeSession.fileExistsAndIsDirectory(NativeSession.java:
438)
at
org.xadisk.filesystem.NativeSession.fileExistsAndIsDirectory(NativeSession.java:
423)
at selected.Example.example2(Example.java:231)
at selected.Example.main(Example.java:349)
I can see the same issue on my machine too (Windows XP 32 bit, Java
1.6.0_19). Some points from my investigation:
1. Behavior of some of the java.io.File APIs are little different in
case of UNC paths than in local paths. For example,
new File("\\\\host1").isDirectory() returns false, while
new File("C:\\").isDirectory() returns true.
Similarly,
new File("\\\\host1").listFiles() returns null.
Though, deeper paths like "\\\\host1\\folder1" are working fine with
these APIs.
2. During the fileExistsAndIsDirectory call, XADisk not only goes one
level up to the immediate ancestor, but goes two levels up (for the
moment, we can skip further internals behind this). As the paths in
your example were like "\\host\a\b", so XADisk landed up on the File
object for "\\host". There, the unexpected File.isDirectory() behavior
(as mentioned above) lead XADisk to believe that the directory "\
\host" does not exist.
3. The error message mentioning permission issue is actually
misleading. The code structure generalizes even the non-existent of an
ancestor directory to the case of "insufficient" permission. (I will
make a note to fix this too.)
4. Your example code runs fine when I replace the path "\\host\a\b"
with "\\host\a\b\\c" (of course, the directory "b" needs to be created
before we run the example). Though, I guess such a constrained
workaround (of having xadisk playground 3 levels below the root
folder) might not work in general.
5. For UNC paths, we will need to do little different handling than
the local paths (mostly around method
TransactionVirtualView:getVirtualViewDirectory). This should be doable
even with Java's behavior mentioned in (1) (look at each shared folder
like "\\host\a" as a separate file-system root instead of thinking "\
\host" to be the root).
I will update here once I have more to share.
Feel free to discuss more.
Thanks,
Nitin
Thanks again for your quick response.
I will try to workaround the "UNC paths not deep enough" issue until a
fix comes in. Would you like me to create a JIRA issue for this?
Thanks,
Kane
I have filed the tracking bug: http://java.net/jira/browse/XADISK-96.
Thanks again for catching this!
Nitin
Sorry for not getting that bug in sooner; I was on holiday with the
family yesterday. I'll be following the issue you raised for me with
interest. Thanks again for your quick response.
Kane