changeset 288:fae289fa5f6c

fix DefferentialTree index bug
author tatsuki
date Sat, 31 Dec 2016 01:48:22 +0900
parents 3705cc48f74b
children 9ebe0ca360be
files src/main/java/jp/ac/u_ryukyu/ie/cr/benchMark/index/CreateIndexBenchMark.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/Index.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/IndexUpdater.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/ParentIndex.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DefaultTransactionManager.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DifferenceTransactionManager.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/traverser/InterfaceTraverser.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/IndexTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/ParentIndexPutTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/defaultTree/IndexTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/defaultTree/ParentIndexPutTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/difference/ParentIndexPutTest.java
diffstat 12 files changed, 371 insertions(+), 253 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/benchMark/index/CreateIndexBenchMark.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/benchMark/index/CreateIndexBenchMark.java	Sat Dec 31 01:48:22 2016 +0900
@@ -19,7 +19,7 @@
         Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
         System.out.println("end create Tree");
 
-        for (int i = 1; i <= 1000; i++) {
+        for (int i = 1; i <= 500; i++) {
             Long t1 = System.currentTimeMillis();
             JungleTree tree = jungle.createNewTree("Tree" + i);
             JungleTreeEditor editor = tree.getJungleTreeEditor();
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/Index.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/Index.java	Sat Dec 31 01:48:22 2016 +0900
@@ -110,7 +110,10 @@
             if (!nodeListOp.isPresent())
                 return false;
             List<TreeNode> nodeList = nodeListOp.get();
-           return nodeList.length() > 0;
+            for (TreeNode n : nodeList) {
+                if (n.equals(node))
+                    return true;
+            }
         }
         return false;
     }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/IndexUpdater.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/IndexUpdater.java	Sat Dec 31 01:48:22 2016 +0900
@@ -29,6 +29,12 @@
         return new Pair<>(newIndex,newParentIndex);
     }
 
+    public Pair<Index, ParentIndex> update() {
+        put(root);
+        return new Pair<>(newIndex,newParentIndex);
+    }
+
+
     private void put(TreeNode currentNode) {
 
         Children children = currentNode.getChildren();
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/ParentIndex.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/store/index/ParentIndex.java	Sat Dec 31 01:48:22 2016 +0900
@@ -36,7 +36,7 @@
     return parentIndex.contain(child);
   }
 
-  private ParentIndex delete(TreeNode child) {
+  public ParentIndex delete(TreeNode child) {
     TreeMap<TreeNode, TreeNode> newParentIndex = parentIndex.delete(child);
     return new ParentIndex(newParentIndex);
   }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DefaultTransactionManager.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DefaultTransactionManager.java	Sat Dec 31 01:48:22 2016 +0900
@@ -68,7 +68,6 @@
         InterfaceTraverser traverser = new InterfaceTraverser(newRoot, index, parentIndex, true);
         traverser.updateIndex(editNodeList);
         //traverser.createIndex();
-        //System.out.println("end");
         TreeContext newTreeContext = new DefaultTreeContext(newRoot, tip, list, uuid, _treeName, nextRevision, traverser);
 
         if (repository.compareAndSet(newTreeContext.prev(), newTreeContext)) {
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DifferenceTransactionManager.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/DifferenceTransactionManager.java	Sat Dec 31 01:48:22 2016 +0900
@@ -4,6 +4,8 @@
 import jp.ac.u_ryukyu.ie.cr.jungle.persistent.ChangeList;
 import jp.ac.u_ryukyu.ie.cr.jungle.persistent.ChangeListWriter;
 import jp.ac.u_ryukyu.ie.cr.jungle.store.TreeContext;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.Index;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.ParentIndex;
 import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.TreeOperationLog;
 import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
 import jp.ac.u_ryukyu.ie.cr.jungle.store.operations.Commit;
@@ -69,7 +71,9 @@
         };
 
         TreeNode root = tip.getRoot();
-        InterfaceTraverser traverser = new InterfaceTraverser(root, true);
+        Index index = tip.getIndex();
+        ParentIndex parentIndex = tip.getParentIndex();
+        InterfaceTraverser traverser = new InterfaceTraverser(root, index, parentIndex, true);
         TreeContext newTreeContext = new DifferenceTreeContext(root, null, tip, list, uuid, _treeName, nextRevision, traverser);
         if (tip.getAppendedNode() == null)
             return DefaultEither.newA(APPENDED_NODE_NULL);
@@ -77,7 +81,7 @@
             Either<Error, TreeNode> either = appendSubTree(subTreeRoot);
             if (either.isA())
                 return DefaultEither.newA(either.a());
-            traverser.createIndex();
+            traverser.updateIndex(tip.getAppendedNode());
             TransactionManager txManager = new DifferenceTransactionManager(writer, newTreeContext, repository, uuid);
             return DefaultEither.newB(txManager);
         }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/traverser/InterfaceTraverser.java	Fri Dec 30 21:12:37 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/traverser/InterfaceTraverser.java	Sat Dec 31 01:48:22 2016 +0900
@@ -56,6 +56,24 @@
         parentIndex = p.right();
     }
 
+    /**
+     *     差分Treeで使う 差分Treeは一度作った木は変更しないのでIndexの中身を削除する必要はない
+     *     なのでputだけで良い
+     */
+    public void updateIndex(TreeNode subTreeRoot) {
+        IndexUpdater indexUpdater = new IndexUpdater(subTreeRoot,index,parentIndex);
+        Pair<Index,ParentIndex> p = indexUpdater.update();
+        index = p.left();
+        parentIndex = p.right();
+    }
+
+    public void updateIndex(List<TreeNode> editedNodeList,TreeNode subTreeNode) {
+        IndexUpdater indexUpdater = new IndexUpdater(subTreeNode,index,parentIndex);
+        Pair<Index,ParentIndex> p = indexUpdater.update(editedNodeList);
+        index = p.left();
+        parentIndex = p.right();
+    }
+
     private TreeNode nextmatch(TreeNode node, Query query) {
         if (query.condition(node))
             return node;
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/IndexTest.java	Fri Dec 30 21:12:37 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-package jp.ac.u_ryukyu.ie.cr.jungle.index;
-
-import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
-import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.TreeMap;
-import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.index.Index;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNodeAttributes;
-import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
-import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.nio.ByteBuffer;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Optional;
-
-import static jp.ac.u_ryukyu.ie.cr.jungle.CreateTreeMethod.createTree;
-
-
-public class IndexTest {
-
-    @Test
-    public void IndexTests() {
-        String key = "key";
-        String indexKey = "indexKey";
-        String addAttributeKey = "addAttributeKey";
-        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
-        jungle.createNewTree("tree");
-        JungleTree tree = jungle.getTreeByName("tree");
-        JungleTreeEditor editor = tree.getJungleTreeEditor();
-        NodePath path = new DefaultNodePath();
-        createTree(editor, key, indexKey, 4, path);
-        TreeNode oldTreeRoot = tree.getRootNode();
-        Index index = tree.getIndex();
-        JungleNodeIterator iterator = new JungleNodeIterator(oldTreeRoot);
-        while (iterator.hasNext()) {
-            TreeNode node = iterator.next();
-            TreeNodeAttributes attribute = node.getAttributes();
-            Iterator<String> keys = attribute.getKeys();
-            while (keys.hasNext()) {       //作った木にちゃんとIndexが張られているかを調べる
-                String attributeKey = keys.next();
-                String value = attribute.getString(attributeKey);
-                Iterator<TreeNode> indexNode = index.get(attributeKey, value);
-                Assert.assertTrue(indexNode.hasNext());
-                Assert.assertEquals(indexNode.next(),node);
-            }
-        }
-
-        JungleTreeEditor editor2 = tree.getJungleTreeEditor();
-        path = path.add(0).add(0).add(2);
-        Either<Error, JungleTreeEditor> either = editor2.putAttribute(path, addAttributeKey, ByteBuffer.wrap("value1".getBytes()));
-        Assert.assertFalse(either.isA());
-        JungleTreeEditor editor3 = either.b();
-        NodePath path2 = new DefaultNodePath();
-        path2 = path2.add(1).add(1).add(2);
-        Either<Error, JungleTreeEditor> either2 = editor3.putAttribute(path2, addAttributeKey, ByteBuffer.wrap("value2".getBytes()));
-        Assert.assertFalse(either2.isA());
-        JungleTreeEditor editor4 = either2.b();
-        Either<Error, JungleTreeEditor> either3 = editor4.success();
-        Assert.assertFalse(either3.isA());
-
-        TreeNode newTreeRoot = tree.getRootNode();
-        Index newIndex = tree.getIndex();
-        iterator = new JungleNodeIterator(newTreeRoot);
-        while (iterator.hasNext()) { //木を編集した際に差分でIndexがアップデートされているかを調べる
-            TreeNode node = iterator.next();
-            TreeNodeAttributes attribute = node.getAttributes();
-            Iterator<String> keys = attribute.getKeys();
-            while (keys.hasNext()) {
-                String attributeKey = keys.next();
-                String value = attribute.getString(attributeKey);
-                Iterator<TreeNode> indexNode = newIndex.get(attributeKey, value);
-                Assert.assertTrue(indexNode.hasNext());
-                Assert.assertEquals(indexNode.next(),node);
-            }
-            newIndex = newIndex.delete(node);
-        }
-
-
-        TreeMap<String, TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>>>  indexList = newIndex.getIndexList(); //差分で更新した際不要な値がIndexに残っていないかを調べる
-        Iterator<String> indexKeys = indexList.keys();
-        while(indexKeys.hasNext()){
-            String indexKeys2 = indexKeys.next();
-            Optional<TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>>> treeMapIndexOp = indexList.get(indexKeys2);
-            Assert.assertTrue(treeMapIndexOp.isPresent());
-            TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>> treeMapIndex = treeMapIndexOp.get();
-            Iterator<String> treeMapIndexKeys = treeMapIndex.keys();
-            while (treeMapIndexKeys.hasNext()) {
-                String treeMapIndexkey = treeMapIndexKeys.next();
-                Optional<jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>> nodeListOp = treeMapIndex.get(treeMapIndexkey);
-                Assert.assertTrue(nodeListOp.isPresent());
-                jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode> nodeList = nodeListOp.get();
-                Assert.assertEquals(nodeList.length(),0);
-            }
-        }
-
-        //編集する際に新しい木に残らないノードがIndexに混ざってないかをしらべる
-        List<TreeNode> deletedNodeList = new LinkedList<>();
-        deletedNodeList = getDeletedNodeList(deletedNodeList, oldTreeRoot, path);
-        deletedNodeList = getDeletedNodeList(deletedNodeList, oldTreeRoot, path2);
-        newIndex = tree.getIndex();
-        for (TreeNode deletedNode : deletedNodeList) {
-            TreeNodeAttributes attribute = deletedNode.getAttributes();
-            Iterator<String> keys = attribute.getKeys();
-            while (keys.hasNext()) {
-                String attributeKey = keys.next();
-                String value = attribute.getString(key);
-                Iterator<TreeNode> newIndexNode = newIndex.get(attributeKey, value);
-                Iterator<TreeNode> oldIndexNode = index.get(attributeKey, value);
-                Assert.assertTrue(newIndexNode.hasNext());
-                Assert.assertTrue(oldIndexNode.hasNext());
-                Assert.assertNotEquals(newIndexNode.next(),oldIndexNode.next());
-                Assert.assertFalse(newIndexNode.hasNext());
-                Assert.assertFalse(oldIndexNode.hasNext());
-            }
-        }
-    }
-
-    private List<TreeNode> getDeletedNodeList(List<TreeNode> list, TreeNode oldTreeRoot, NodePath path) {
-        TreeNode node = oldTreeRoot;
-        for (Integer i : path.pop().right()) {
-            Children children = node.getChildren();
-            Either<Error, TreeNode> either = children.at(i);
-            Assert.assertFalse(either.isA());
-            node = either.b();
-            list.add(node);
-        }
-        return list;
-    }
-
-
-}
\ No newline at end of file
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/ParentIndexPutTest.java	Fri Dec 30 21:12:37 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-package jp.ac.u_ryukyu.ie.cr.jungle.index;
-
-import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
-import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.index.ParentIndex;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
-import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
-import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Optional;
-
-import static jp.ac.u_ryukyu.ie.cr.jungle.CreateTreeMethod.createTree;
-
-
-/**
- * Created by e115731 on 15/05/06.
- */
-public class ParentIndexPutTest {
-    private String key = "key";
-    private String indexKey = "indexKey";
-    private String addAttributeKey = "addAttributeKey";
-    @Test
-    public void ParentIndexPut() {
-        Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTraverser());
-        jungle.createNewTree("tree");
-        JungleTree tree = jungle.getTreeByName("tree");
-        JungleTreeEditor editor = tree.getJungleTreeEditor();
-        NodePath path = new DefaultNodePath();
-        createTree(editor,key,indexKey,3,path);
-        TreeNode oldTreeRoot = tree.getRootNode();
-        ParentIndex parentIndex = tree.getParentIndex();
-        JungleNodeIterator iterator = new JungleNodeIterator(oldTreeRoot);
-        while(iterator.hasNext()){
-            TreeNode parent = iterator.next();
-            Children children = parent.getChildren();
-            for (TreeNode child : children) {
-                Optional<TreeNode> parentOp = parentIndex.get(child);
-                Assert.assertTrue(parentOp.isPresent());
-                TreeNode parentIndexGetNode = parentOp.get();
-                Assert.assertEquals(parent,parentIndexGetNode);
-            }
-       }
-
-        JungleTreeEditor editor2 = tree.getJungleTreeEditor();
-        path = path.add(0).add(0).add(2);
-        Either<Error, JungleTreeEditor> either = editor2.putAttribute(path,addAttributeKey, ByteBuffer.wrap("value".getBytes()) );
-        Assert.assertFalse(either.isA());
-        JungleTreeEditor editor3 = either.b();
-        NodePath path2 = new DefaultNodePath();
-        path2 = path2.add(1).add(1).add(2);
-        Either<Error, JungleTreeEditor> either2 = editor3.putAttribute(path2,addAttributeKey, ByteBuffer.wrap("value".getBytes()) );
-        Assert.assertFalse(either2.isA());
-        JungleTreeEditor editor4 = either2.b();
-        Either<Error, JungleTreeEditor> either3 = editor4.success();
-        Assert.assertFalse(either3.isA());
-
-        TreeNode newTreeRoot = tree.getRootNode();
-        ParentIndex newTreeParentIndex = tree.getParentIndex();
-        iterator = new JungleNodeIterator(newTreeRoot);
-        while(iterator.hasNext()){
-            TreeNode parent = iterator.next();
-            Children children = parent.getChildren();
-            for (TreeNode child : children) {
-                Optional<TreeNode> parentOp = newTreeParentIndex.get(child);
-                Assert.assertTrue(parentOp.isPresent());
-                TreeNode parentIndexGetNode = parentOp.get();
-                Assert.assertEquals(parent,parentIndexGetNode);
-            }
-        }
-        List<TreeNode> deletedNodeList = new LinkedList<>();
-        deletedNodeList = getDeletedNodeList(deletedNodeList,oldTreeRoot,path);
-        deletedNodeList = getDeletedNodeList(deletedNodeList,oldTreeRoot,path2);
-
-        for (TreeNode deletedNode : deletedNodeList) {
-            Optional<TreeNode> optional = newTreeParentIndex.get(deletedNode);
-            Assert.assertFalse(optional.isPresent());
-        }
-    }
-
-    private List<TreeNode> getDeletedNodeList(List<TreeNode> list, TreeNode oldTreeRoot, NodePath path) {
-        TreeNode node = oldTreeRoot;
-        for (Integer i : path.pop().right()) {
-            Children children = node.getChildren();
-            Either<Error, TreeNode> either = children.at(i);
-            Assert.assertFalse(either.isA());
-            node = either.b();
-            list.add(node);
-        }
-        return list;
-    }
-
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/defaultTree/IndexTest.java	Sat Dec 31 01:48:22 2016 +0900
@@ -0,0 +1,142 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.index.defaultTree;
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
+import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.Index;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNodeAttributes;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+import static jp.ac.u_ryukyu.ie.cr.jungle.CreateTreeMethod.createTree;
+
+
+public class IndexTest {
+
+    @Test
+    public void IndexTests() {
+        String key = "key";
+        String indexKey = "indexKey";
+        String addAttributeKey = "addAttributeKey";
+        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
+        jungle.createNewTree("tree");
+        JungleTree tree = jungle.getTreeByName("tree");
+        JungleTreeEditor editor = tree.getJungleTreeEditor();
+        NodePath path = new DefaultNodePath();
+        createTree(editor, key, indexKey, 4, path);
+        TreeNode oldTreeRoot = tree.getRootNode();
+        Index index = tree.getIndex();
+        JungleNodeIterator iterator = new JungleNodeIterator(oldTreeRoot);
+        while (iterator.hasNext()) {
+            TreeNode node = iterator.next();
+            TreeNodeAttributes attribute = node.getAttributes();
+            Iterator<String> keys = attribute.getKeys();
+            while (keys.hasNext()) {       //作った木にちゃんとIndexが張られているかを調べる
+                String attributeKey = keys.next();
+                String value = attribute.getString(attributeKey);
+                Iterator<TreeNode> indexNode = index.get(attributeKey, value);
+                Assert.assertTrue(indexNode.hasNext());
+                Assert.assertEquals(indexNode.next(),node);
+            }
+        }
+
+        JungleTreeEditor editor2 = tree.getJungleTreeEditor();
+        path = path.add(0).add(0).add(2);
+        Either<Error, JungleTreeEditor> either = editor2.putAttribute(path, addAttributeKey, ByteBuffer.wrap("value1".getBytes()));
+        Assert.assertFalse(either.isA());
+        JungleTreeEditor editor3 = either.b();
+        NodePath path2 = new DefaultNodePath();
+        path2 = path2.add(1).add(1).add(2);
+        Either<Error, JungleTreeEditor> either2 = editor3.putAttribute(path2, addAttributeKey, ByteBuffer.wrap("value2".getBytes()));
+        Assert.assertFalse(either2.isA());
+        JungleTreeEditor editor4 = either2.b();
+        Either<Error, JungleTreeEditor> either3 = editor4.success();
+        Assert.assertFalse(either3.isA());
+
+        TreeNode newTreeRoot = tree.getRootNode();
+        Index newIndex = tree.getIndex();
+        iterator = new JungleNodeIterator(newTreeRoot);
+        while (iterator.hasNext()) { //木を編集した際に差分でIndexがアップデートされているかを調べる
+            TreeNode node = iterator.next();
+            TreeNodeAttributes attribute = node.getAttributes();
+            Iterator<String> keys = attribute.getKeys();
+            while (keys.hasNext()) {
+                String attributeKey = keys.next();
+                String value = attribute.getString(attributeKey);
+                Iterator<TreeNode> indexNode = newIndex.get(attributeKey, value);
+                Assert.assertTrue(indexNode.hasNext());
+                Assert.assertEquals(indexNode.next(),node);
+            }
+            newIndex = newIndex.delete(node);
+        }
+
+
+        TreeMap<String, TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>>>  indexList = newIndex.getIndexList(); //差分で更新した際不要な値がIndexに残っていないかを調べる
+        Iterator<String> indexKeys = indexList.keys();
+        while(indexKeys.hasNext()){
+            String indexKeys2 = indexKeys.next();
+            Optional<TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>>> treeMapIndexOp = indexList.get(indexKeys2);
+            Assert.assertTrue(treeMapIndexOp.isPresent());
+            TreeMap<String, jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>> treeMapIndex = treeMapIndexOp.get();
+            Iterator<String> treeMapIndexKeys = treeMapIndex.keys();
+            while (treeMapIndexKeys.hasNext()) {
+                String treeMapIndexkey = treeMapIndexKeys.next();
+                Optional<jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode>> nodeListOp = treeMapIndex.get(treeMapIndexkey);
+                Assert.assertTrue(nodeListOp.isPresent());
+                jp.ac.u_ryukyu.ie.cr.jungle.data.list.List<TreeNode> nodeList = nodeListOp.get();
+                Assert.assertEquals(nodeList.length(),0);
+            }
+        }
+
+        //編集する際に新しい木に残らないノードがIndexに混ざってないかをしらべる
+        List<TreeNode> deletedNodeList = new LinkedList<>();
+        deletedNodeList = getDeletedNodeList(deletedNodeList, oldTreeRoot, path);
+        deletedNodeList = getDeletedNodeList(deletedNodeList, oldTreeRoot, path2);
+        newIndex = tree.getIndex();
+        for (TreeNode deletedNode : deletedNodeList) {
+            TreeNodeAttributes attribute = deletedNode.getAttributes();
+            Iterator<String> keys = attribute.getKeys();
+            while (keys.hasNext()) {
+                String attributeKey = keys.next();
+                String value = attribute.getString(key);
+                Iterator<TreeNode> newIndexNode = newIndex.get(attributeKey, value);
+                Iterator<TreeNode> oldIndexNode = index.get(attributeKey, value);
+                Assert.assertTrue(newIndexNode.hasNext());
+                Assert.assertTrue(oldIndexNode.hasNext());
+                Assert.assertNotEquals(newIndexNode.next(),oldIndexNode.next());
+                Assert.assertFalse(newIndexNode.hasNext());
+                Assert.assertFalse(oldIndexNode.hasNext());
+            }
+        }
+    }
+
+    private List<TreeNode> getDeletedNodeList(List<TreeNode> list, TreeNode oldTreeRoot, NodePath path) {
+        TreeNode node = oldTreeRoot;
+        for (Integer i : path.pop().right()) {
+            Children children = node.getChildren();
+            Either<Error, TreeNode> either = children.at(i);
+            Assert.assertFalse(either.isA());
+            node = either.b();
+            list.add(node);
+        }
+        return list;
+    }
+
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/defaultTree/ParentIndexPutTest.java	Sat Dec 31 01:48:22 2016 +0900
@@ -0,0 +1,105 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.index.defaultTree;
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
+import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.ParentIndex;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+import static jp.ac.u_ryukyu.ie.cr.jungle.CreateTreeMethod.createTree;
+
+
+/**
+ * Created by e115731 on 15/05/06.
+ */
+public class ParentIndexPutTest {
+    private String key = "key";
+    private String indexKey = "indexKey";
+    private String addAttributeKey = "addAttributeKey";
+    @Test
+    public void ParentIndexPut() {
+        Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTraverser());
+        jungle.createNewTree("tree");
+        JungleTree tree = jungle.getTreeByName("tree");
+        JungleTreeEditor editor = tree.getJungleTreeEditor();
+        NodePath path = new DefaultNodePath();
+        createTree(editor,key,indexKey,3,path);
+        TreeNode oldTreeRoot = tree.getRootNode();
+        ParentIndex parentIndex = tree.getParentIndex();
+        JungleNodeIterator iterator = new JungleNodeIterator(oldTreeRoot);
+        while(iterator.hasNext()){
+            TreeNode parent = iterator.next();
+            Children children = parent.getChildren();
+            for (TreeNode child : children) {
+                Optional<TreeNode> parentOp = parentIndex.get(child);
+                Assert.assertTrue(parentOp.isPresent());
+                TreeNode parentIndexGetNode = parentOp.get();
+                Assert.assertEquals(parent,parentIndexGetNode);
+            }
+       }
+
+        JungleTreeEditor editor2 = tree.getJungleTreeEditor();
+        path = path.add(0).add(0).add(2);
+        Either<Error, JungleTreeEditor> either = editor2.putAttribute(path,addAttributeKey, ByteBuffer.wrap("value".getBytes()) );
+        Assert.assertFalse(either.isA());
+        JungleTreeEditor editor3 = either.b();
+        NodePath path2 = new DefaultNodePath();
+        path2 = path2.add(1).add(1).add(2);
+        Either<Error, JungleTreeEditor> either2 = editor3.putAttribute(path2,addAttributeKey, ByteBuffer.wrap("value".getBytes()) );
+        Assert.assertFalse(either2.isA());
+        JungleTreeEditor editor4 = either2.b();
+        Either<Error, JungleTreeEditor> either3 = editor4.success();
+        Assert.assertFalse(either3.isA());
+
+        TreeNode newTreeRoot = tree.getRootNode();
+        ParentIndex newTreeParentIndex = tree.getParentIndex();
+        iterator = new JungleNodeIterator(newTreeRoot);
+        while(iterator.hasNext()){
+            TreeNode parent = iterator.next();
+            Children children = parent.getChildren();
+            for (TreeNode child : children) {
+                Optional<TreeNode> parentOp = newTreeParentIndex.get(child);
+                Assert.assertTrue(parentOp.isPresent());
+                TreeNode parentIndexGetNode = parentOp.get();
+                Assert.assertEquals(parent,parentIndexGetNode);
+            }
+        }
+        List<TreeNode> deletedNodeList = new LinkedList<>();
+        deletedNodeList = getDeletedNodeList(deletedNodeList,oldTreeRoot,path);
+        deletedNodeList = getDeletedNodeList(deletedNodeList,oldTreeRoot,path2);
+
+        for (TreeNode deletedNode : deletedNodeList) {
+            Optional<TreeNode> optional = newTreeParentIndex.get(deletedNode);
+            Assert.assertFalse(optional.isPresent());
+        }
+    }
+
+    private List<TreeNode> getDeletedNodeList(List<TreeNode> list, TreeNode oldTreeRoot, NodePath path) {
+        TreeNode node = oldTreeRoot;
+        for (Integer i : path.pop().right()) {
+            Children children = node.getChildren();
+            Either<Error, TreeNode> either = children.at(i);
+            Assert.assertFalse(either.isA());
+            node = either.b();
+            list.add(node);
+        }
+        return list;
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/index/difference/ParentIndexPutTest.java	Sat Dec 31 01:48:22 2016 +0900
@@ -0,0 +1,88 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.index.difference;
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.Index;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.index.ParentIndex;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+
+public class ParentIndexPutTest {
+    private Index index;
+    private ParentIndex parentIndex;
+
+    @Test
+    public void ParentIndexPut() {
+        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
+        jungle.createNewTree("tree");
+        JungleTree tree = jungle.createNewDifferenceTree("Tree");
+        JungleTreeEditor editor = tree.getJungleTreeEditor();
+        NodePath path = new DefaultNodePath();
+        for (int j = 0; j < 10; j++) { //木の構築
+            Either<Error, JungleTreeEditor> either = editor.addNewChildAt(path, 0);
+            Assert.assertFalse(either.isA());
+            editor = either.b();
+            either = editor.putAttribute(path, "key", ByteBuffer.wrap("value".getBytes()));
+            Assert.assertFalse(either.isA());
+            editor = either.b();
+            path = path.add(0);
+        }
+        Either<Error, JungleTreeEditor> either = editor.success();
+        Assert.assertFalse(either.isA());
+        editor = either.b();
+
+        parentIndex = tree.getParentIndex();
+        index = tree.getIndex();
+        TreeNode root = tree.getRootNode();
+        checkIndex(root);//indexが張られているかを調べる
+        Assert.assertTrue(parentIndex.isEmpty());
+
+
+        //一回木を更新する
+        editor = tree.getJungleTreeEditor();
+        path = new DefaultNodePath();
+        either = editor.addNewChildAt(path, 0);
+        Assert.assertFalse(either.isA());
+        editor = either.b();
+        either = editor.putAttribute(path, "key", ByteBuffer.wrap("value".getBytes()));
+        Assert.assertFalse(either.isA());
+        editor = either.b();
+        either = editor.success();
+        Assert.assertFalse(either.isA());
+
+        //更新後にちゃんとIndexが貼れているかを調べる
+        parentIndex = tree.getParentIndex();
+        index = tree.getIndex();
+        root = tree.getRootNode();
+        checkIndex(root);
+        Assert.assertTrue(parentIndex.isEmpty());
+
+    System.out.println("asdfasdfa");
+    }
+
+    public void checkIndex(TreeNode currentNode) {
+        Children children = currentNode.getChildren();
+        for (TreeNode child : children) {
+            Optional<TreeNode> parentOp = parentIndex.get(child);
+            Assert.assertTrue(parentOp.isPresent());
+            TreeNode parent = parentOp.get();
+            Assert.assertEquals(parent,currentNode);
+            checkIndex(child);
+            parentIndex = parentIndex.delete(child);
+        }
+
+    }
+}