Set paths on blocks after hashing.

This commit is contained in:
akwizgran
2018-12-06 17:41:27 +00:00
parent bd9ebe75a0
commit 438d200afe
6 changed files with 67 additions and 30 deletions

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.api.io; package org.briarproject.bramble.api.io;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.tree.TreeHash; import org.briarproject.bramble.api.sync.tree.TreeHash;
import java.util.List; import java.util.List;
@@ -18,10 +17,4 @@ public interface BlockSink {
*/ */
void setPath(HashingId h, int blockNumber, List<TreeHash> path) void setPath(HashingId h, int blockNumber, List<TreeHash> path)
throws DbException; throws DbException;
/**
* Sets the permanent ID of the message with the given temporary ID. The
* temporary ID is no longer valid once this method has been called.
*/
void setMessageId(HashingId h, MessageId m) throws DbException;
} }

View File

@@ -1,8 +1,21 @@
package org.briarproject.bramble.api.sync.tree; package org.briarproject.bramble.api.sync.tree;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class LeafNode extends TreeNode { public class LeafNode extends TreeNode {
public LeafNode(TreeHash hash, int blockNumber) { public LeafNode(TreeHash hash, int blockNumber) {
super(hash, 0, blockNumber, blockNumber); super(hash, 0, blockNumber, blockNumber);
} }
@Override
public TreeNode getLeftChild() {
throw new UnsupportedOperationException();
}
@Override
public TreeNode getRightChild() {
throw new UnsupportedOperationException();
}
} }

View File

@@ -1,9 +1,26 @@
package org.briarproject.bramble.api.sync.tree; package org.briarproject.bramble.api.sync.tree;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class ParentNode extends TreeNode { public class ParentNode extends TreeNode {
private final TreeNode left, right;
public ParentNode(TreeHash hash, TreeNode left, TreeNode right) { public ParentNode(TreeHash hash, TreeNode left, TreeNode right) {
super(hash, Math.max(left.getHeight(), right.getHeight()) + 1, super(hash, Math.max(left.getHeight(), right.getHeight()) + 1,
left.getFirstBlockNumber(), right.getLastBlockNumber()); left.getFirstBlockNumber(), right.getLastBlockNumber());
this.left = left;
this.right = right;
}
@Override
public TreeNode getLeftChild() {
return left;
}
@Override
public TreeNode getRightChild() {
return right;
} }
} }

View File

@@ -4,8 +4,6 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.io.BlockSink; import org.briarproject.bramble.api.io.BlockSink;
import org.briarproject.bramble.api.io.HashingId; import org.briarproject.bramble.api.io.HashingId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -16,8 +14,8 @@ public interface StreamHasher {
/** /**
* Reads the given input stream, divides the data into blocks, stores * Reads the given input stream, divides the data into blocks, stores
* the blocks and the resulting hash tree using the given block sink and * the blocks and the resulting hash tree using the given block sink and
* temporary ID, and returns the message ID. * temporary ID, and returns the hash tree.
*/ */
MessageId hash(InputStream in, BlockSink sink, HashingId h, GroupId g, TreeNode hash(InputStream in, BlockSink sink, HashingId h)
long timestamp) throws IOException, DbException; throws IOException, DbException;
} }

View File

@@ -1,6 +1,9 @@
package org.briarproject.bramble.api.sync.tree; package org.briarproject.bramble.api.sync.tree;
public class TreeNode { import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public abstract class TreeNode {
private final TreeHash hash; private final TreeHash hash;
private final int height, firstBlockNumber, lastBlockNumber; private final int height, firstBlockNumber, lastBlockNumber;
@@ -28,4 +31,8 @@ public class TreeNode {
public int getLastBlockNumber() { public int getLastBlockNumber() {
return lastBlockNumber; return lastBlockNumber;
} }
public abstract TreeNode getLeftChild();
public abstract TreeNode getRightChild();
} }

View File

@@ -4,16 +4,14 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.io.BlockSink; import org.briarproject.bramble.api.io.BlockSink;
import org.briarproject.bramble.api.io.HashingId; import org.briarproject.bramble.api.io.HashingId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.tree.LeafNode;
import org.briarproject.bramble.api.sync.tree.StreamHasher; import org.briarproject.bramble.api.sync.tree.StreamHasher;
import org.briarproject.bramble.api.sync.tree.TreeHash; import org.briarproject.bramble.api.sync.tree.TreeHash;
import org.briarproject.bramble.api.sync.tree.TreeHasher; import org.briarproject.bramble.api.sync.tree.TreeHasher;
import org.briarproject.bramble.api.sync.tree.TreeNode;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.LinkedList;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
@@ -27,21 +25,19 @@ import static org.briarproject.bramble.api.sync.SyncConstants.MAX_BLOCK_LENGTH;
class StreamHasherImpl implements StreamHasher { class StreamHasherImpl implements StreamHasher {
private final TreeHasher treeHasher; private final TreeHasher treeHasher;
private final MessageFactory messageFactory;
private final Provider<HashTree> hashTreeProvider; private final Provider<HashTree> hashTreeProvider;
@Inject @Inject
StreamHasherImpl(TreeHasher treeHasher, MessageFactory messageFactory, StreamHasherImpl(TreeHasher treeHasher,
Provider<HashTree> hashTreeProvider) { Provider<HashTree> hashTreeProvider) {
this.treeHasher = treeHasher; this.treeHasher = treeHasher;
this.messageFactory = messageFactory;
this.hashTreeProvider = hashTreeProvider; this.hashTreeProvider = hashTreeProvider;
} }
@Override @Override
public MessageId hash(InputStream in, BlockSink sink, HashingId h, public TreeNode hash(InputStream in, BlockSink sink, HashingId h)
GroupId g, long timestamp) throws IOException, DbException { throws IOException, DbException {
HashTree hashTree = hashTreeProvider.get(); HashTree tree = hashTreeProvider.get();
byte[] block = new byte[MAX_BLOCK_LENGTH]; byte[] block = new byte[MAX_BLOCK_LENGTH];
int read; int read;
for (int blockNumber = 0; (read = read(in, block)) > 0; blockNumber++) { for (int blockNumber = 0; (read = read(in, block)) > 0; blockNumber++) {
@@ -49,14 +45,11 @@ class StreamHasherImpl implements StreamHasher {
if (read == block.length) data = block; if (read == block.length) data = block;
else data = copyOfRange(block, 0, read); else data = copyOfRange(block, 0, read);
sink.putBlock(h, blockNumber, data); sink.putBlock(h, blockNumber, data);
LeafNode leaf = treeHasher.hashBlock(blockNumber, data); tree.addLeaf(treeHasher.hashBlock(blockNumber, data));
hashTree.addLeaf(leaf);
} }
// TODO: Set paths on block sink TreeNode root = tree.getRoot();
TreeHash rootHash = hashTree.getRoot().getHash(); setPaths(sink, h, root, new LinkedList<>());
MessageId m = messageFactory.getMessageId(g, timestamp, rootHash); return root;
sink.setMessageId(h, m);
return m;
} }
/** /**
@@ -73,4 +66,20 @@ class StreamHasherImpl implements StreamHasher {
} }
return offset; return offset;
} }
private void setPaths(BlockSink sink, HashingId h, TreeNode node,
LinkedList<TreeHash> path) throws DbException {
if (node.getHeight() == 0) {
// We've reached a leaf - store the path
sink.setPath(h, node.getFirstBlockNumber(), path);
} else {
// Add the right child's hash to the path and traverse the left
path.addFirst(node.getRightChild().getHash());
setPaths(sink, h, node.getLeftChild(), path);
// Add the left child's hash to the path and traverse the right
path.removeFirst();
path.addFirst(node.getLeftChild().getHash());
setPaths(sink, h, node.getRightChild(), path);
}
}
} }