Mercurial > hg > Members > shoshi > jungle > jungle-core
changeset 303:a5f7565f3a4b
add RedBlackTreeInterfaceTraverser and this test
author | tatsuki |
---|---|
date | Sun, 08 Jan 2017 12:23:48 +0900 |
parents | 0767620e6f5f |
children | b6118ca2c2c2 67c330ef2472 |
files | src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/DefaultJungle.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/query/traverser/RedBlackTreeTraverser.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/query/traverser/nodeiterator/RedBlackTreeNodeIterator.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/RedBlackTreeTransactionManager.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/traverse/RedBlackInterfaceTraverserTest.java |
diffstat | 5 files changed, 234 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/DefaultJungle.java Sat Jan 07 18:02:53 2017 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/DefaultJungle.java Sun Jan 08 12:23:48 2017 +0900 @@ -7,6 +7,7 @@ import jp.ac.u_ryukyu.ie.cr.jungle.persistent.NullJournal; import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.DifferentialInterfaceTraverser; import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.InterfaceTraverser; +import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.RedBlackTreeTraverser; import jp.ac.u_ryukyu.ie.cr.jungle.store.TreeContext; import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.DefaultTreeOperationLog; import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.TreeOperationLog; @@ -180,7 +181,7 @@ }; TreeNode rootNode = new EmptyTreeNode(); - InterfaceTraverser traverser = new DefaultInterfaceTraverser(rootNode, true); + InterfaceTraverser traverser = new RedBlackTreeTraverser(rootNode); TreeContext tc = new DefaultTreeContext(rootNode, null, list, uuid, treeName, 0, traverser); JungleTree newTree = new RedBlackJungleTree(tc, uuid, journal.getWriter(), redBlackTreeEditor, balanceKey); if (trees.putIfAbsent(treeName, newTree) != null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/query/traverser/RedBlackTreeTraverser.java Sun Jan 08 12:23:48 2017 +0900 @@ -0,0 +1,137 @@ +package jp.ac.u_ryukyu.ie.cr.jungle.query.traverser; + +import jp.ac.u_ryukyu.ie.cr.jungle.data.list.List; +import jp.ac.u_ryukyu.ie.cr.jungle.query.Query; +import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.nodeiterator.DefaultNodeIterator; +import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.nodeiterator.RedBlackTreeNodeIterator; +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.transaction.node.TreeNode; + +import java.util.Iterator; + + +public class RedBlackTreeTraverser implements InterfaceTraverser { + private TreeNode root; + + public RedBlackTreeTraverser(TreeNode root) { + this.root = root; + } + + @Override + public Index getIndex() { + return null; //使わない 赤黒木は自身がIndexなので、特別なIndexは無い + } + + @Override + public ParentIndex getParentIndex() { + return null; // 上に同じ、回転処理で構造が変わるため、自身の木構造でデータを表現しない、つまり親を知る必要はない + } + + @Override + public void createIndex() { // 上に同じ Indexを張る必要はない + } + + @Override + public void updateIndex(List<TreeNode> editedNodeList) { //上に同じ + + } + + @Override + public void updateIndex(TreeNode subTreeRoot) { //上に同じ + + } + + @Override + public Iterator<TreeNode> find(Query query) { //balanceKeyを使わない場合全探索なのでDefaultInterfaceTraverserと変わらない + Iterator<TreeNode> nodeIterator = new DefaultNodeIterator(root); + TreeNode firstMatchNode = null; + for (; nodeIterator.hasNext(); ) { + firstMatchNode = nextmatch(nodeIterator.next(), query); + if (firstMatchNode != null) + break; + } + + final TreeNode finalFirstMatchNode = firstMatchNode; + + return new Iterator<TreeNode>() { + + TreeNode matchNode = finalFirstMatchNode; + + @Override + public boolean hasNext() { + if (matchNode == null) { + return false; + } + return true; + } + + @Override + public TreeNode next() { + TreeNode currentPair = matchNode; + for (; nodeIterator.hasNext(); ) { + matchNode = nextmatch(nodeIterator.next(), query); + if (matchNode != null) + return currentPair; + } + matchNode = null; + return currentPair; + } + + @Override + public void remove() { + } + + }; + } + + @Override + public Iterator<TreeNode> find(Query query, String key, String searchValue) { + Iterator<TreeNode> nodeIterator = new RedBlackTreeNodeIterator(root,key,searchValue); + TreeNode firstMatchNode = null; + for (; nodeIterator.hasNext(); ) { + firstMatchNode = nextmatch(nodeIterator.next(), query); + if (firstMatchNode != null) + break; + } + + final TreeNode finalFirstMatchNode = firstMatchNode; + + return new Iterator<TreeNode>() { + + TreeNode matchNode = finalFirstMatchNode; + + @Override + public boolean hasNext() { + if (matchNode == null) { + return false; + } + return true; + } + + @Override + public TreeNode next() { + TreeNode currentPair = matchNode; + for (; nodeIterator.hasNext(); ) { + matchNode = nextmatch(nodeIterator.next(), query); + if (matchNode != null) + return currentPair; + } + matchNode = null; + return currentPair; + } + + @Override + public void remove() { + } + + }; + } + + private TreeNode nextmatch(TreeNode node, Query query) { + if (query.condition(node)) + return node; + return null; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/query/traverser/nodeiterator/RedBlackTreeNodeIterator.java Sun Jan 08 12:23:48 2017 +0900 @@ -0,0 +1,48 @@ +package jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.nodeiterator; + +import jp.ac.u_ryukyu.ie.cr.jungle.core.Attributes; +import jp.ac.u_ryukyu.ie.cr.jungle.core.Children; +import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode; + +import java.nio.ByteBuffer; +import java.util.Iterator; + + +public class RedBlackTreeNodeIterator implements Iterator<TreeNode> { + private TreeNode next; + public RedBlackTreeNodeIterator(TreeNode root, String key, String searchValue) { + ByteBuffer searchValueBf = ByteBuffer.wrap(searchValue.getBytes()); + next = search(root,key,searchValueBf); + } + + private TreeNode search(TreeNode target,String key,ByteBuffer searchValueBf){ + if (target == null) + return null; + Attributes attribute = target.getAttributes(); + ByteBuffer targetValue = attribute.get(key); + + if (targetValue.hashCode() - searchValueBf.hashCode() < 0) { + Children children = target.getChildren(); + TreeNode child = children.at(0).b(); + return search(child,key,searchValueBf); + } else if (targetValue.hashCode() - searchValueBf.hashCode() > 0){ + Children children = target.getChildren(); + TreeNode child = children.at(1).b(); + return search(child,key,searchValueBf); + } else { + return target; + } + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public TreeNode next() { + TreeNode current = next; + next = null; + return current; + } +}
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/RedBlackTreeTransactionManager.java Sat Jan 07 18:02:53 2017 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/manager/RedBlackTreeTransactionManager.java Sun Jan 08 12:23:48 2017 +0900 @@ -4,12 +4,12 @@ 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.query.traverser.InterfaceTraverser; +import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.RedBlackTreeTraverser; import jp.ac.u_ryukyu.ie.cr.jungle.store.TreeContext; import jp.ac.u_ryukyu.ie.cr.jungle.store.logger.TreeOperationLog; import jp.ac.u_ryukyu.ie.cr.jungle.store.operations.TreeOperation; import jp.ac.u_ryukyu.ie.cr.jungle.transaction.context.DefaultTreeContext; import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode; -import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.DefaultInterfaceTraverser; import jp.ac.u_ryukyu.ie.cr.jungle.util.DefaultEither; import jp.ac.u_ryukyu.ie.cr.jungle.util.Either; import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.DefaultError; @@ -61,7 +61,7 @@ }; - InterfaceTraverser traverser = new DefaultInterfaceTraverser(newRoot, true); + InterfaceTraverser traverser = new RedBlackTreeTraverser(newRoot); TreeContext newTreeContext = new DefaultTreeContext(newRoot, tip, list, uuid, _treeName, nextRevision, traverser); if (repository.compareAndSet(newTreeContext.prev(), newTreeContext)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/traverse/RedBlackInterfaceTraverserTest.java Sun Jan 08 12:23:48 2017 +0900 @@ -0,0 +1,45 @@ +package jp.ac.u_ryukyu.ie.cr.jungle.traverse; + +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.persistent.NullJournal; +import jp.ac.u_ryukyu.ie.cr.jungle.query.traverser.InterfaceTraverser; +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 junit.framework.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.util.Iterator; + +public class RedBlackInterfaceTraverserTest { + private String balanceKey = "key"; + + @Test + public void RedBlackInterfaceTraverserTests() { + Jungle jungle = new DefaultJungle(new NullJournal(), "hoge", new DefaultTraverser()); + jungle.createNewRedBlackTree("RedBlackTree", balanceKey); + JungleTree tree = jungle.getTreeByName("RedBlackTree"); + JungleTreeEditor editor = tree.getJungleTreeEditor(); + NodePath path = new DefaultNodePath(); + for (int nodeCount = 0; nodeCount < 100; nodeCount++) { + ByteBuffer value = ByteBuffer.wrap(("value" + nodeCount).getBytes()); + Either<Error,JungleTreeEditor> either = editor.addNewChildAndPutAttribute(path, 0, balanceKey, value); + Assert.assertFalse(either.isA()); + editor = either.b(); + } + Either<Error,JungleTreeEditor> either = editor.success(); + Assert.assertFalse(either.isA()); + InterfaceTraverser traverser = tree.getTraverser(true); + Iterator<TreeNode> iterator = traverser.find((TreeNode node) -> { + return true; + },balanceKey,"value5"); + Assert.assertTrue(iterator.hasNext()); + } +}