Author: bleny Date: 2010-06-10 11:30:17 +0200 (Thu, 10 Jun 2010) New Revision: 71 Url: http://nuiton.org/repositories/revision/diswork/71 Log: implementation move + test, gestion de l'echec du bootstrap dans kademlia + test, traces dans la demo Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/Demo.java trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java trunk/diswork-fs/src/main/resources/log4j.properties trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/Demo.java =================================================================== --- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/Demo.java 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/Demo.java 2010-06-10 09:30:17 UTC (rev 71) @@ -90,6 +90,7 @@ } } catch (IOException e) { log.error(e); + System.out.println("error occured " + e); } try { Thread.sleep(15 * 1000); @@ -142,11 +143,13 @@ } } catch (IOException e) { log.error(e); + System.out.println("error occured " + e); } try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { log.info("sleep interrupted", e); + System.out.println("error occured " + e); } } } Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java =================================================================== --- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/DisworkFileSystem.java 2010-06-10 09:30:17 UTC (rev 71) @@ -692,4 +692,121 @@ + doubleSeparator); } } + + /** + * move a file, a directory a link. May be used for renaming purpose + * @param path the path to the object to move + * @param destination the full path of the target + * @throws IOException + */ + public void move(String path, String destination) throws IOException { + checkPathSyntax(path); + checkPathSyntax(destination); + + String pathParent = EntryUtil.getParentFromPath(path); + String pathName = EntryUtil.getNameFromPath(path); + String destinationParent = EntryUtil.getParentFromPath(destination); + String destinationName = EntryUtil.getNameFromPath(destination); + + move(pathParent, pathName, destinationParent, destinationName); + + } + + protected void move(String pathParent, String pathName, + String destinationParent, String destinationName) throws IOException { + + String entryParent = walk(pathParent); + + if (entryParent == null) { + throw new IOException(pathParent + " directory doesn't exists"); + } + + if (EntryUtil.isDirectory(entryParent)) { + + String destinationParentEntry = walk(destinationParent); + if (destinationParentEntry == null) { + throw new IOException(destinationParentEntry + " directory" + + "doesn't exists"); + } + + if (EntryUtil.isDirectory(destinationParentEntry)) { + + // we are now in actual directories for old path and destination + + String parentContent = storage.getDirectory( + EntryUtil.getIdFromEntry(entryParent)); + String oldEntry = EntryUtil.findEntryInDirectory(parentContent, + pathName); + if (oldEntry == null) { + throw new IOException("no element " + pathName + " in " + + pathParent); + } + + String parentId = EntryUtil.getIdFromEntry(entryParent); + String destinationParentId = EntryUtil.getIdFromEntry(destinationParentEntry); + // update directory content + int numberOfTry = 0; + boolean lockAcquired = false; + while (numberOfTry <= LOCK_MAX_NUMBER_OF_TRY && !lockAcquired) { + lockAcquired = storage.tryToLock(parentId) + && storage.tryToLock(destinationParentId); + if (lockAcquired) { + // we have locked, do the update + parentContent = storage.getDirectory(parentId); + String newContent = EntryUtil.removeEntryFromEntries(parentContent, pathName); + storage.putDirectory(parentId, newContent); + + + String destinationParentContent = storage.getDirectory(destinationParentId); + newContent = EntryUtil.addEntryToDirectoryContent(destinationParentContent, + EntryUtil.getTypeFromEntry(oldEntry), + destinationName, + EntryUtil.getIdFromEntry(oldEntry)); + storage.putDirectory(destinationParentId, newContent); + + storage.unLock(parentId); + storage.unLock(destinationParentId); + } else { + log.info(pathParent + " is locked"); + try { + Thread.sleep(LOCK_WAIT); + } catch (InterruptedException e) { + log.info("wait for lock interrupted", e); + throw new IOException + ("interrupted while trying to acquire lock", e); + } + } + } + + if (!lockAcquired) { + // fail, parent dir have not been written + throw new ConcurrentModificationException + ("can't write " + pathParent + " directory is locked"); + } + + } else if (EntryUtil.isLink(destinationParentEntry)) { + String linkTarget = storage.getLink( + EntryUtil.getIdFromEntry(destinationParentEntry)); + String newTarget = EntryUtil.resolveLink(destinationParent, linkTarget); + move(newTarget, pathName, destinationParent, destinationName); + } else if (EntryUtil.isFile(destinationParentEntry)) { + throw new IOException(destinationParent + " is not a directory"); + } else { + log.warn("strange entry" + destinationParentEntry); + throw new IOException("strange entry" + destinationParentEntry); + } + + } else if (EntryUtil.isLink(entryParent)) { + String linkTarget = storage.getLink( + EntryUtil.getIdFromEntry(entryParent)); + String newTarget = EntryUtil.resolveLink(pathParent, linkTarget); + move(pathParent, pathName, newTarget, destinationName); + } else if (EntryUtil.isFile(entryParent)) { + throw new IOException(pathParent + " is not a directory"); + } else { + log.warn("strange entry" + entryParent); + throw new IOException("strange entry" + entryParent); + } + + } } \ No newline at end of file Modified: trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java =================================================================== --- trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/main/java/org/nuiton/diswork/fs/storage/KademliaDisworkMap.java 2010-06-10 09:30:17 UTC (rev 71) @@ -40,6 +40,7 @@ import org.nuiton.diswork.fs.DisworkFileSystemConfig; import org.planx.xmlstore.routing.Identifier; import org.planx.xmlstore.routing.Kademlia; +import org.planx.xmlstore.routing.RoutingException; public class KademliaDisworkMap implements DisworkMap { @@ -48,13 +49,19 @@ protected Kademlia kad; public KademliaDisworkMap(DisworkFileSystemConfig config) throws IOException { + log.info("booting kademlia dht on port " + config.getUsedPort()); kad = new Kademlia(Identifier.randomIdentifier(), config.getUsedPort()); if (config.getBootstrapIp() != null) { InetSocketAddress bootstrap = new InetSocketAddress( config.getBootstrapIp(), config.getBootstrapPort()); - kad.connect(bootstrap); + try { + kad.connect(bootstrap); + } catch (RoutingException e) { + log.error("bootstrap node is unreachable", e); + throw e; + } } //Identifier.IDSIZE = 1024; Modified: trunk/diswork-fs/src/main/resources/log4j.properties =================================================================== --- trunk/diswork-fs/src/main/resources/log4j.properties 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/main/resources/log4j.properties 2010-06-10 09:30:17 UTC (rev 71) @@ -6,4 +6,5 @@ log4j.appender.stdout.layout.ConversionPattern=%d %5p [%t] (%F:%L) %M - %m%n # package level log4j.logger.org.nuiton.disworkfs=WARN +#log4j.logger.org.nuiton.diswork.fs.storage.KademliaDisworkMap=INFO log4j.logger.org.nuiton.disworkfs.Demo=INFO \ No newline at end of file Modified: trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java =================================================================== --- trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/AbstractDisworkFileSystemTest.java 2010-06-10 09:30:17 UTC (rev 71) @@ -327,7 +327,7 @@ } @Test - public void testLinks() throws Exception { + public void testLinks() throws Exception { fileSystem.createDirectory("/dir"); fileSystem.createDirectory("/dir/subdir"); fileSystem.createDirectory("/otherdir"); @@ -358,4 +358,40 @@ assertEquals(1, readResult.size()); assertTrue(readResult.contains("subdir")); } + + @Test + public void testMove() throws Exception { + fileSystem.createDirectory("/dir"); + fileSystem.createDirectory("/dir/subdir"); + fileSystem.createDirectory("/dir/subdir/subsubdir"); + fileSystem.createSymbolicLink("/dir/link", "subdir"); + fileSystem.write("/dir/file", new FileInputStream(randomFilePath)); + + fileSystem.createDirectory("/otherdir"); + fileSystem.move("/dir/subdir", "/otherdir/subdir"); + fileSystem.move("/dir/link", "/otherdir/link"); + fileSystem.move("/dir/file", "/otherdir/newfile"); + + List<String> readDir = fileSystem.readDirectory("/dir"); + for (String c : readDir) { + System.out.println(c); + } + assertTrue(readDir.isEmpty()); + + readDir = fileSystem.readDirectory("/otherdir"); + assertEquals(3, readDir.size()); + + assertTrue(fileSystem.exists("/otherdir/newfile")); + assertTrue(fileSystem.exists("/otherdir/subdir/subsubdir")); + + // FIXME 20100610 bleny after moving a link, it still points the old target + + //assertTrue(fileSystem.exists("/otherdir/link/subsubdir")); + /* + readDir = fileSystem.readDirectory("/otherdir/link"); + for (String e : readDir) { + System.out.println(e); + } + */ + } } Modified: trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java =================================================================== --- trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java 2010-06-09 08:40:08 UTC (rev 70) +++ trunk/diswork-fs/src/test/java/org/nuiton/diswork/fs/storage/KademliaDisworkMapTest.java 2010-06-10 09:30:17 UTC (rev 71) @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -18,10 +19,12 @@ @Before public void setUp() throws Exception { - DisworkFileSystemConfig config1 = DisworkFileSystemConfig.newKademliaDisworkConfig(); + DisworkFileSystemConfig config1 = + DisworkFileSystemConfig.newKademliaDisworkConfig(); map1 = new KademliaDisworkMap(config1); - DisworkFileSystemConfig config2 = DisworkFileSystemConfig.newKademliaDisworkConfig(config1.getUsedPort()); + DisworkFileSystemConfig config2 = DisworkFileSystemConfig + .newKademliaDisworkConfig(config1.getUsedPort()); map2 = new KademliaDisworkMap(config2); } @@ -63,4 +66,18 @@ // if keys set is too small, there are collisions assertEquals(paths.size(), keys.size()); } + + /** + * Tests that in exception is raised when attempting to connect using + * a bad bootstrap + * @throws Exception + */ + @Test(expected = IOException.class) + public void testBadBootrap() throws Exception { + DisworkFileSystemConfig config1 = + DisworkFileSystemConfig.newKademliaDisworkConfig(); + config1.setBootstrapIp("microsoft.com"); + config1.setBootstrapPort(80); + new KademliaDisworkMap(config1); + } }