Rename blockstore::Key -> blockstore::BlockId

This commit is contained in:
Sebastian Messmer 2017-09-17 02:07:27 +01:00
parent 10e11f67e2
commit 5458af7c52
146 changed files with 2013 additions and 2014 deletions

View File

@ -15,7 +15,7 @@ using cpputils::unique_ref;
using cpputils::Data;
using blobstore::onblocks::datanodestore::DataLeafNode;
using blobstore::onblocks::datanodestore::DataNodeLayout;
using blockstore::Key;
using blockstore::BlockId;
using blobstore::onblocks::datatreestore::LeafHandle;
namespace blobstore {
@ -131,7 +131,7 @@ void BlobOnBlocks::write(const void *source, uint64_t offset, uint64_t count) {
if (leafDataOffset == 0 && leafDataSize == leaf.nodeStore()->layout().maxBytesPerLeaf()) {
Data leafData(leafDataSize);
std::memcpy(leafData.data(), (uint8_t*)source + indexOfFirstLeafByte - offset, leafDataSize);
leaf.nodeStore()->overwriteLeaf(leaf.key(), std::move(leafData));
leaf.nodeStore()->overwriteLeaf(leaf.blockId(), std::move(leafData));
} else {
//TODO Simplify formula, make it easier to understand
leaf.node()->write((uint8_t *) source + indexOfFirstLeafByte - offset + leafDataOffset, leafDataOffset,
@ -152,8 +152,8 @@ void BlobOnBlocks::flush() {
_datatree->flush();
}
const Key &BlobOnBlocks::key() const {
return _datatree->key();
const BlockId &BlobOnBlocks::blockId() const {
return _datatree->blockId();
}
unique_ref<DataTreeRef> BlobOnBlocks::releaseTree() {

View File

@ -22,7 +22,7 @@ public:
BlobOnBlocks(cpputils::unique_ref<parallelaccessdatatreestore::DataTreeRef> datatree);
~BlobOnBlocks();
const blockstore::Key &key() const override;
const blockstore::BlockId &blockId() const override;
uint64_t size() const override;
void resize(uint64_t numBytes) override;

View File

@ -15,7 +15,7 @@ using cpputils::make_unique_ref;
using blockstore::BlockStore;
using blockstore::parallelaccess::ParallelAccessBlockStore;
using blockstore::Key;
using blockstore::BlockId;
using cpputils::dynamic_pointer_move;
using boost::optional;
using boost::none;
@ -38,8 +38,8 @@ unique_ref<Blob> BlobStoreOnBlocks::create() {
return make_unique_ref<BlobOnBlocks>(_dataTreeStore->createNewTree());
}
optional<unique_ref<Blob>> BlobStoreOnBlocks::load(const Key &key) {
auto tree = _dataTreeStore->load(key);
optional<unique_ref<Blob>> BlobStoreOnBlocks::load(const BlockId &blockId) {
auto tree = _dataTreeStore->load(blockId);
if (tree == none) {
return none;
}
@ -52,8 +52,8 @@ void BlobStoreOnBlocks::remove(unique_ref<Blob> blob) {
_dataTreeStore->remove((*_blob)->releaseTree());
}
void BlobStoreOnBlocks::remove(const Key &key) {
_dataTreeStore->remove(key);
void BlobStoreOnBlocks::remove(const BlockId &blockId) {
_dataTreeStore->remove(blockId);
}
uint64_t BlobStoreOnBlocks::virtualBlocksizeBytes() const {

View File

@ -20,10 +20,10 @@ public:
~BlobStoreOnBlocks();
cpputils::unique_ref<Blob> create() override;
boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::Key &key) override;
boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::BlockId &blockId) override;
void remove(cpputils::unique_ref<Blob> blob) override;
void remove(const blockstore::Key &key) override;
void remove(const blockstore::BlockId &blockId) override;
//TODO Test blocksizeBytes/numBlocks/estimateSpaceForNumBlocksLeft
//virtual means "space we can use" as opposed to "space it takes on the disk" (i.e. virtual is without headers, checksums, ...)

View File

@ -7,7 +7,7 @@ using blockstore::BlockStore;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using blockstore::Key;
using blockstore::BlockId;
using std::vector;
namespace blobstore {
@ -25,25 +25,25 @@ DataInnerNode::DataInnerNode(DataNodeView view)
DataInnerNode::~DataInnerNode() {
}
unique_ref<DataInnerNode> DataInnerNode::InitializeNewNode(unique_ref<Block> block, const DataNodeLayout &layout, uint8_t depth, const vector<Key> &children) {
unique_ref<DataInnerNode> DataInnerNode::InitializeNewNode(unique_ref<Block> block, const DataNodeLayout &layout, uint8_t depth, const vector<BlockId> &children) {
ASSERT(children.size() >= 1, "An inner node must have at least one child");
Data data = _serializeChildren(children);
return make_unique_ref<DataInnerNode>(DataNodeView::initialize(std::move(block), layout, DataNode::FORMAT_VERSION_HEADER, depth, children.size(), std::move(data)));
}
unique_ref<DataInnerNode> DataInnerNode::CreateNewNode(BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const vector<Key> &children) {
unique_ref<DataInnerNode> DataInnerNode::CreateNewNode(BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const vector<BlockId> &children) {
ASSERT(children.size() >= 1, "An inner node must have at least one child");
Data data = _serializeChildren(children);
return make_unique_ref<DataInnerNode>(DataNodeView::create(blockStore, layout, DataNode::FORMAT_VERSION_HEADER, depth, children.size(), std::move(data)));
}
Data DataInnerNode::_serializeChildren(const vector<Key> &children) {
Data DataInnerNode::_serializeChildren(const vector<BlockId> &children) {
Data data(sizeof(ChildEntry) * children.size());
uint32_t i = 0;
for (const Key &child : children) {
reinterpret_cast<ChildEntry*>(data.data())[i++].setKey(child);
for (const BlockId &child : children) {
reinterpret_cast<ChildEntry*>(data.data())[i++].setBlockId(child);
}
return data;
}
@ -89,12 +89,12 @@ void DataInnerNode::addChild(const DataNode &child) {
ASSERT(numChildren() < maxStoreableChildren(), "Adding more children than we can store");
ASSERT(child.depth() == depth()-1, "The child that should be added has wrong depth");
node().setSize(node().Size()+1);
LastChild()->setKey(child.key());
LastChild()->setBlockId(child.blockId());
}
void DataInnerNode::removeLastChild() {
ASSERT(node().Size() > 1, "There is no child to remove");
LastChild()->setKey(Key::Null());
LastChild()->setBlockId(BlockId::Null());
node().setSize(node().Size()-1);
}

View File

@ -11,8 +11,8 @@ namespace datanodestore {
class DataInnerNode final: public DataNode {
public:
static cpputils::unique_ref<DataInnerNode> InitializeNewNode(cpputils::unique_ref<blockstore::Block> block, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::Key> &children);
static cpputils::unique_ref<DataInnerNode> CreateNewNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::Key> &children);
static cpputils::unique_ref<DataInnerNode> InitializeNewNode(cpputils::unique_ref<blockstore::Block> block, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
static cpputils::unique_ref<DataInnerNode> CreateNewNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint8_t depth, const std::vector<blockstore::BlockId> &children);
DataInnerNode(DataNodeView block);
~DataInnerNode();
@ -26,7 +26,7 @@ public:
uint32_t numChildren() const;
void addChild(const DataNode &child_key);
void addChild(const DataNode &child_blockId);
void removeLastChild();
@ -40,7 +40,7 @@ private:
const ChildEntry *ChildrenBegin() const;
const ChildEntry *ChildrenEnd() const;
static cpputils::Data _serializeChildren(const std::vector<blockstore::Key> &children);
static cpputils::Data _serializeChildren(const std::vector<blockstore::BlockId> &children);
DISALLOW_COPY_AND_ASSIGN(DataInnerNode);
};

View File

@ -10,15 +10,15 @@ namespace datanodestore{
struct DataInnerNode_ChildEntry final {
public:
blockstore::Key key() const {
return blockstore::Key::FromBinary(_keydata);
blockstore::BlockId blockId() const {
return blockstore::BlockId::FromBinary(_blockIdData);
}
private:
void setKey(const blockstore::Key &key) {
key.ToBinary(_keydata);
void setBlockId(const blockstore::BlockId &blockId) {
blockId.ToBinary(_blockIdData);
}
friend class DataInnerNode;
uint8_t _keydata[blockstore::Key::BINARY_LENGTH];
uint8_t _blockIdData[blockstore::BlockId::BINARY_LENGTH];
DISALLOW_COPY_AND_ASSIGN(DataInnerNode_ChildEntry);
};

View File

@ -4,7 +4,7 @@
using blockstore::Block;
using cpputils::Data;
using blockstore::Key;
using blockstore::BlockId;
using blockstore::BlockStore;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
@ -31,10 +31,10 @@ unique_ref<DataLeafNode> DataLeafNode::CreateNewNode(BlockStore *blockStore, con
return make_unique_ref<DataLeafNode>(DataNodeView::create(blockStore, layout, DataNode::FORMAT_VERSION_HEADER, 0, size, std::move(data)));
}
unique_ref<DataLeafNode> DataLeafNode::OverwriteNode(BlockStore *blockStore, const DataNodeLayout &layout, const Key &key, Data data) {
unique_ref<DataLeafNode> DataLeafNode::OverwriteNode(BlockStore *blockStore, const DataNodeLayout &layout, const BlockId &blockId, Data data) {
ASSERT(data.size() == layout.maxBytesPerLeaf(), "Data passed in is too large for one leaf.");
uint32_t size = data.size();
return make_unique_ref<DataLeafNode>(DataNodeView::overwrite(blockStore, layout, DataNode::FORMAT_VERSION_HEADER, 0, size, key, std::move(data)));
return make_unique_ref<DataLeafNode>(DataNodeView::overwrite(blockStore, layout, DataNode::FORMAT_VERSION_HEADER, 0, size, blockId, std::move(data)));
}
void DataLeafNode::read(void *target, uint64_t offset, uint64_t size) const {

View File

@ -12,7 +12,7 @@ class DataInnerNode;
class DataLeafNode final: public DataNode {
public:
static cpputils::unique_ref<DataLeafNode> CreateNewNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, cpputils::Data data);
static cpputils::unique_ref<DataLeafNode> OverwriteNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, const blockstore::Key &key, cpputils::Data data);
static cpputils::unique_ref<DataLeafNode> OverwriteNode(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, const blockstore::BlockId &blockId, cpputils::Data data);
DataLeafNode(DataNodeView block);
~DataLeafNode();

View File

@ -5,7 +5,7 @@
#include <blockstore/utils/BlockStoreUtils.h>
using blockstore::Block;
using blockstore::Key;
using blockstore::BlockId;
using std::runtime_error;
using cpputils::unique_ref;
@ -31,8 +31,8 @@ const DataNodeView &DataNode::node() const {
return _node;
}
const Key &DataNode::key() const {
return _node.key();
const BlockId &DataNode::blockId() const {
return _node.blockId();
}
uint8_t DataNode::depth() const {
@ -43,7 +43,7 @@ unique_ref<DataInnerNode> DataNode::convertToNewInnerNode(unique_ref<DataNode> n
auto block = node->_node.releaseBlock();
blockstore::utils::fillWithZeroes(block.get());
return DataInnerNode::InitializeNewNode(std::move(block), layout, first_child.depth()+1, {first_child.key()});
return DataInnerNode::InitializeNewNode(std::move(block), layout, first_child.depth()+1, {first_child.blockId()});
}
void DataNode::flush() const {

View File

@ -15,7 +15,7 @@ class DataNode {
public:
virtual ~DataNode();
const blockstore::Key &key() const;
const blockstore::BlockId &blockId() const;
uint8_t depth() const;

View File

@ -8,7 +8,7 @@
using blockstore::BlockStore;
using blockstore::Block;
using blockstore::Key;
using blockstore::BlockId;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
@ -41,7 +41,7 @@ unique_ref<DataNode> DataNodeStore::load(unique_ref<Block> block) {
}
}
unique_ref<DataInnerNode> DataNodeStore::createNewInnerNode(uint8_t depth, const vector<Key> &children) {
unique_ref<DataInnerNode> DataNodeStore::createNewInnerNode(uint8_t depth, const vector<BlockId> &children) {
ASSERT(children.size() >= 1, "Inner node must have at least one child");
return DataInnerNode::CreateNewNode(_blockstore.get(), _layout, depth, children);
}
@ -50,12 +50,12 @@ unique_ref<DataLeafNode> DataNodeStore::createNewLeafNode(Data data) {
return DataLeafNode::CreateNewNode(_blockstore.get(), _layout, std::move(data));
}
unique_ref<DataLeafNode> DataNodeStore::overwriteLeaf(const Key &key, Data data) {
return DataLeafNode::OverwriteNode(_blockstore.get(), _layout, key, std::move(data));
unique_ref<DataLeafNode> DataNodeStore::overwriteLeaf(const BlockId &blockId, Data data) {
return DataLeafNode::OverwriteNode(_blockstore.get(), _layout, blockId, std::move(data));
}
optional<unique_ref<DataNode>> DataNodeStore::load(const Key &key) {
auto block = _blockstore->load(key);
optional<unique_ref<DataNode>> DataNodeStore::load(const BlockId &blockId) {
auto block = _blockstore->load(blockId);
if (block == none) {
return none;
} else {
@ -80,13 +80,13 @@ unique_ref<DataNode> DataNodeStore::overwriteNodeWith(unique_ref<DataNode> targe
}
void DataNodeStore::remove(unique_ref<DataNode> node) {
Key key = node->key();
BlockId blockId = node->blockId();
cpputils::destruct(std::move(node));
remove(key);
remove(blockId);
}
void DataNodeStore::remove(const Key &key) {
_blockstore->remove(key);
void DataNodeStore::remove(const BlockId &blockId) {
_blockstore->remove(blockId);
}
void DataNodeStore::removeSubtree(unique_ref<DataNode> node) {
@ -99,23 +99,23 @@ void DataNodeStore::removeSubtree(unique_ref<DataNode> node) {
auto inner = dynamic_pointer_move<DataInnerNode>(node);
ASSERT(inner != none, "Is neither a leaf nor an inner node");
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
removeSubtree((*inner)->depth()-1, (*inner)->getChild(i)->key());
removeSubtree((*inner)->depth()-1, (*inner)->getChild(i)->blockId());
}
remove(std::move(*inner));
}
void DataNodeStore::removeSubtree(uint8_t depth, const Key &key) {
void DataNodeStore::removeSubtree(uint8_t depth, const BlockId &blockId) {
if (depth == 0) {
remove(key);
remove(blockId);
} else {
auto node = load(key);
auto node = load(blockId);
ASSERT(node != none, "Node for removeSubtree not found");
auto inner = dynamic_pointer_move<DataInnerNode>(*node);
ASSERT(inner != none, "Is not an inner node, but depth was not zero");
ASSERT((*inner)->depth() == depth, "Wrong depth given");
for (uint32_t i = 0; i < (*inner)->numChildren(); ++i) {
removeSubtree(depth-1, (*inner)->getChild(i)->key());
removeSubtree(depth-1, (*inner)->getChild(i)->blockId());
}
remove(std::move(*inner));
}

View File

@ -5,7 +5,7 @@
#include <memory>
#include <cpp-utils/macros.h>
#include "DataNodeView.h"
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
namespace blockstore{
class Block;
@ -28,21 +28,21 @@ public:
DataNodeLayout layout() const;
boost::optional<cpputils::unique_ref<DataNode>> load(const blockstore::Key &key);
boost::optional<cpputils::unique_ref<DataNode>> load(const blockstore::BlockId &blockId);
static cpputils::unique_ref<DataNode> load(cpputils::unique_ref<blockstore::Block> block);
cpputils::unique_ref<DataLeafNode> createNewLeafNode(cpputils::Data data);
cpputils::unique_ref<DataInnerNode> createNewInnerNode(uint8_t depth, const std::vector<blockstore::Key> &children);
cpputils::unique_ref<DataInnerNode> createNewInnerNode(uint8_t depth, const std::vector<blockstore::BlockId> &children);
cpputils::unique_ref<DataNode> createNewNodeAsCopyFrom(const DataNode &source);
cpputils::unique_ref<DataNode> overwriteNodeWith(cpputils::unique_ref<DataNode> target, const DataNode &source);
cpputils::unique_ref<DataLeafNode> overwriteLeaf(const blockstore::Key &key, cpputils::Data data);
cpputils::unique_ref<DataLeafNode> overwriteLeaf(const blockstore::BlockId &blockId, cpputils::Data data);
void remove(cpputils::unique_ref<DataNode> node);
void remove(const blockstore::Key &key);
void removeSubtree(uint8_t depth, const blockstore::Key &key);
void remove(const blockstore::BlockId &blockId);
void removeSubtree(uint8_t depth, const blockstore::BlockId &blockId);
void removeSubtree(cpputils::unique_ref<DataNode> node);
//TODO Test blocksizeBytes/numBlocks/estimateSpaceForNumBlocksLeft

View File

@ -81,10 +81,10 @@ public:
return DataNodeView(std::move(block));
}
static DataNodeView overwrite(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint16_t formatVersion, uint8_t depth, uint32_t size, const blockstore::Key &key, cpputils::Data data) {
static DataNodeView overwrite(blockstore::BlockStore *blockStore, const DataNodeLayout &layout, uint16_t formatVersion, uint8_t depth, uint32_t size, const blockstore::BlockId &blockId, cpputils::Data data) {
ASSERT(data.size() <= layout.datasizeBytes(), "Data is too large for node");
cpputils::Data serialized = _serialize(layout, formatVersion, depth, size, std::move(data));
auto block = blockStore->overwrite(key, std::move(serialized));
auto block = blockStore->overwrite(blockId, std::move(serialized));
return DataNodeView(std::move(block));
}
@ -145,8 +145,8 @@ public:
return *_block;
}
const blockstore::Key &key() const {
return _block->key();
const blockstore::BlockId &blockId() const {
return _block->blockId();
}
void flush() const {

View File

@ -13,7 +13,7 @@
#include <cpp-utils/assert/assert.h>
#include "impl/LeafTraverser.h"
using blockstore::Key;
using blockstore::BlockId;
using blobstore::onblocks::datanodestore::DataNodeStore;
using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataInnerNode;
@ -40,14 +40,14 @@ namespace onblocks {
namespace datatreestore {
DataTree::DataTree(DataNodeStore *nodeStore, unique_ref<DataNode> rootNode)
: _mutex(), _nodeStore(nodeStore), _rootNode(std::move(rootNode)), _key(_rootNode->key()), _numLeavesCache(none) {
: _mutex(), _nodeStore(nodeStore), _rootNode(std::move(rootNode)), _blockId(_rootNode->blockId()), _numLeavesCache(none) {
}
DataTree::~DataTree() {
}
const Key &DataTree::key() const {
return _key;
const BlockId &DataTree::blockId() const {
return _blockId;
}
void DataTree::flush() const {
@ -89,7 +89,7 @@ uint32_t DataTree::_computeNumLeaves(const DataNode &node) const {
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(node);
uint64_t numLeavesInLeftChildren = (uint64_t)(inner.numChildren()-1) * leavesPerFullChild(inner);
auto lastChild = _nodeStore->load(inner.LastChild()->key());
auto lastChild = _nodeStore->load(inner.LastChild()->blockId());
ASSERT(lastChild != none, "Couldn't load last child");
uint64_t numLeavesInRightChild = _computeNumLeaves(**lastChild);
@ -138,7 +138,7 @@ uint64_t DataTree::_numStoredBytes(const DataNode &root) const {
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(root);
uint64_t numBytesInLeftChildren = (inner.numChildren()-1) * leavesPerFullChild(inner) * _nodeStore->layout().maxBytesPerLeaf();
auto lastChild = _nodeStore->load(inner.LastChild()->key());
auto lastChild = _nodeStore->load(inner.LastChild()->blockId());
ASSERT(lastChild != none, "Couldn't load last child");
uint64_t numBytesInRightChild = _numStoredBytes(**lastChild);
@ -172,7 +172,7 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
ASSERT(neededChildrenForRightBorderNode <= node->numChildren(), "Node has too few children");
// All children to the right of the new right-border-node are removed including their subtree.
while(node->numChildren() > neededChildrenForRightBorderNode) {
_nodeStore->removeSubtree(node->depth()-1, node->LastChild()->key());
_nodeStore->removeSubtree(node->depth()-1, node->LastChild()->blockId());
node->removeLastChild();
}
};

View File

@ -8,7 +8,7 @@
#include "../datanodestore/DataNodeView.h"
//TODO Replace with C++14 once std::shared_mutex is supported
#include <boost/thread/shared_mutex.hpp>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include "LeafHandle.h"
namespace blobstore {
@ -27,7 +27,7 @@ public:
DataTree(datanodestore::DataNodeStore *nodeStore, cpputils::unique_ref<datanodestore::DataNode> rootNode);
~DataTree();
const blockstore::Key &key() const;
const blockstore::BlockId &blockId() const;
//Returning uint64_t, because calculations handling this probably need to be done in 64bit to support >4GB blobs.
uint64_t maxBytesPerLeaf() const;
@ -48,7 +48,7 @@ private:
mutable boost::shared_mutex _mutex;
datanodestore::DataNodeStore *_nodeStore;
cpputils::unique_ref<datanodestore::DataNode> _rootNode;
blockstore::Key _key; // Key is stored in a member variable, since _rootNode is nullptr while traversing, but we still want to be able to return the key.
blockstore::BlockId _blockId; // BlockId is stored in a member variable, since _rootNode is nullptr while traversing, but we still want to be able to return the blockId.
mutable boost::optional<uint32_t> _numLeavesCache;
cpputils::unique_ref<datanodestore::DataNode> releaseRootNode();

View File

@ -22,8 +22,8 @@ DataTreeStore::DataTreeStore(unique_ref<DataNodeStore> nodeStore)
DataTreeStore::~DataTreeStore() {
}
optional<unique_ref<DataTree>> DataTreeStore::load(const blockstore::Key &key) {
auto node = _nodeStore->load(key);
optional<unique_ref<DataTree>> DataTreeStore::load(const blockstore::BlockId &blockId) {
auto node = _nodeStore->load(blockId);
if (node == none) {
return none;
}
@ -39,8 +39,8 @@ void DataTreeStore::remove(unique_ref<DataTree> tree) {
_nodeStore->removeSubtree(tree->releaseRootNode());
}
void DataTreeStore::remove(const blockstore::Key &key) {
auto tree = load(key);
void DataTreeStore::remove(const blockstore::BlockId &blockId) {
auto tree = load(blockId);
ASSERT(tree != none, "Tree to remove not found");
remove(std::move(*tree));
}

View File

@ -5,7 +5,7 @@
#include <memory>
#include <cpp-utils/macros.h>
#include <cpp-utils/pointer/unique_ref.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <boost/optional.hpp>
#include "../datanodestore/DataNodeStore.h"
@ -19,12 +19,12 @@ public:
DataTreeStore(cpputils::unique_ref<datanodestore::DataNodeStore> nodeStore);
~DataTreeStore();
boost::optional<cpputils::unique_ref<DataTree>> load(const blockstore::Key &key);
boost::optional<cpputils::unique_ref<DataTree>> load(const blockstore::BlockId &blockId);
cpputils::unique_ref<DataTree> createNewTree();
void remove(cpputils::unique_ref<DataTree> tree);
void remove(const blockstore::Key &key);
void remove(const blockstore::BlockId &blockId);
//TODO Test blocksizeBytes/numBlocks/estimateSpaceForNumBlocksLeft
uint64_t virtualBlocksizeBytes() const;

View File

@ -8,24 +8,24 @@ using boost::none;
using cpputils::dynamic_pointer_move;
using blobstore::onblocks::datanodestore::DataLeafNode;
using blobstore::onblocks::datanodestore::DataNodeStore;
using blockstore::Key;
using blockstore::BlockId;
namespace blobstore {
namespace onblocks {
namespace datatreestore {
LeafHandle::LeafHandle(DataNodeStore *nodeStore, const Key &key)
: _nodeStore(nodeStore), _key(key), _leaf(cpputils::null<DataLeafNode>()) {
LeafHandle::LeafHandle(DataNodeStore *nodeStore, const BlockId &blockId)
: _nodeStore(nodeStore), _blockId(blockId), _leaf(cpputils::null<DataLeafNode>()) {
}
LeafHandle::LeafHandle(DataNodeStore *nodeStore, DataLeafNode *node)
: _nodeStore(nodeStore), _key(node->key()),
: _nodeStore(nodeStore), _blockId(node->blockId()),
_leaf(WithoutOwnership<DataLeafNode>(node)) {
}
DataLeafNode *LeafHandle::node() {
if (_leaf.get() == nullptr) {
auto loaded = _nodeStore->load(_key);
auto loaded = _nodeStore->load(_blockId);
ASSERT(loaded != none, "Leaf not found");
auto leaf = dynamic_pointer_move<DataLeafNode>(*loaded);
ASSERT(leaf != none, "Loaded leaf is not leaf node");

View File

@ -4,7 +4,7 @@
#include <cpp-utils/macros.h>
#include <cpp-utils/pointer/optional_ownership_ptr.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
namespace blobstore {
namespace onblocks {
@ -16,12 +16,12 @@ namespace blobstore {
class LeafHandle final {
public:
LeafHandle(datanodestore::DataNodeStore *nodeStore, const blockstore::Key &key);
LeafHandle(datanodestore::DataNodeStore *nodeStore, const blockstore::BlockId &blockId);
LeafHandle(datanodestore::DataNodeStore *nodeStore, datanodestore::DataLeafNode *node);
LeafHandle(LeafHandle &&rhs) = default;
const blockstore::Key &key() {
return _key;
const blockstore::BlockId &blockId() {
return _blockId;
}
datanodestore::DataLeafNode *node();
@ -32,7 +32,7 @@ namespace blobstore {
private:
datanodestore::DataNodeStore *_nodeStore;
blockstore::Key _key;
blockstore::BlockId _blockId;
cpputils::optional_ownership_ptr<datanodestore::DataLeafNode> _leaf;
DISALLOW_COPY_AND_ASSIGN(LeafHandle);

View File

@ -78,11 +78,11 @@ namespace blobstore {
return DataNode::convertToNewInnerNode(std::move(root), _nodeStore->layout(), *copyOfOldRoot);
}
void LeafTraverser::_traverseExistingSubtree(const blockstore::Key &key, uint8_t depth, uint32_t beginIndex, uint32_t endIndex, uint32_t leafOffset, bool isLeftBorderOfTraversal, bool isRightBorderNode, bool growLastLeaf, function<void (uint32_t index, bool isRightBorderLeaf, LeafHandle leaf)> onExistingLeaf, function<Data (uint32_t index)> onCreateLeaf, function<void (DataInnerNode *node)> onBacktrackFromSubtree) {
void LeafTraverser::_traverseExistingSubtree(const blockstore::BlockId &blockId, uint8_t depth, uint32_t beginIndex, uint32_t endIndex, uint32_t leafOffset, bool isLeftBorderOfTraversal, bool isRightBorderNode, bool growLastLeaf, function<void (uint32_t index, bool isRightBorderLeaf, LeafHandle leaf)> onExistingLeaf, function<Data (uint32_t index)> onCreateLeaf, function<void (DataInnerNode *node)> onBacktrackFromSubtree) {
if (depth == 0) {
ASSERT(beginIndex <= 1 && endIndex <= 1,
"If root node is a leaf, the (sub)tree has only one leaf - access indices must be 0 or 1.");
LeafHandle leafHandle(_nodeStore, key);
LeafHandle leafHandle(_nodeStore, blockId);
if (growLastLeaf) {
if (leafHandle.node()->numBytes() != _nodeStore->layout().maxBytesPerLeaf()) {
leafHandle.node()->resize(_nodeStore->layout().maxBytesPerLeaf());
@ -92,9 +92,9 @@ namespace blobstore {
onExistingLeaf(leafOffset, isRightBorderNode, std::move(leafHandle));
}
} else {
auto node = _nodeStore->load(key);
auto node = _nodeStore->load(blockId);
if (node == none) {
throw std::runtime_error("Couldn't find child node " + key.ToString());
throw std::runtime_error("Couldn't find child node " + blockId.ToString());
}
auto inner = dynamic_pointer_move<DataInnerNode>(*node);
@ -122,9 +122,9 @@ namespace blobstore {
// we still have to descend to the last old child to fill it with leaves and grow the last old leaf.
if (isLeftBorderOfTraversal && beginChild >= numChildren) {
ASSERT(numChildren > 0, "Node doesn't have children.");
auto childKey = root->getChild(numChildren-1)->key();
auto childBlockId = root->getChild(numChildren-1)->blockId();
uint32_t childOffset = (numChildren-1) * leavesPerChild;
_traverseExistingSubtree(childKey, root->depth()-1, leavesPerChild, leavesPerChild, childOffset, true, false, true,
_traverseExistingSubtree(childBlockId, root->depth()-1, leavesPerChild, leavesPerChild, childOffset, true, false, true,
[] (uint32_t /*index*/, bool /*isRightBorderNode*/, LeafHandle /*leaf*/) {ASSERT(false, "We don't actually traverse any leaves.");},
[] (uint32_t /*index*/) -> Data {ASSERT(false, "We don't actually traverse any leaves.");},
[] (DataInnerNode* /*node*/) {ASSERT(false, "We don't actually traverse any leaves.");});
@ -132,7 +132,7 @@ namespace blobstore {
// Traverse existing children
for (uint32_t childIndex = beginChild; childIndex < std::min(endChild, numChildren); ++childIndex) {
auto childKey = root->getChild(childIndex)->key();
auto childBlockId = root->getChild(childIndex)->blockId();
uint32_t childOffset = childIndex * leavesPerChild;
uint32_t localBeginIndex = utils::maxZeroSubtraction(beginIndex, childOffset);
uint32_t localEndIndex = std::min(leavesPerChild, endIndex - childOffset);
@ -140,7 +140,7 @@ namespace blobstore {
bool isLastExistingChild = (childIndex == numChildren - 1);
bool isLastChild = isLastExistingChild && (numChildren == endChild);
ASSERT(localEndIndex <= leavesPerChild, "We don't want the child to add a tree level because it doesn't have enough space for the traversal.");
_traverseExistingSubtree(childKey, root->depth()-1, localBeginIndex, localEndIndex, leafOffset + childOffset, isLeftBorderOfTraversal && isFirstChild,
_traverseExistingSubtree(childBlockId, root->depth()-1, localBeginIndex, localEndIndex, leafOffset + childOffset, isLeftBorderOfTraversal && isFirstChild,
isRightBorderNode && isLastChild, shouldGrowLastExistingLeaf && isLastExistingChild, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree);
}
@ -175,7 +175,7 @@ namespace blobstore {
uint32_t beginChild = beginIndex/leavesPerChild;
uint32_t endChild = utils::ceilDivision(endIndex, leavesPerChild);
vector<blockstore::Key> children;
vector<blockstore::BlockId> children;
children.reserve(endChild);
// TODO Remove redundancy of following two for loops by using min/max for calculating the parameters of the recursive call.
// Create gap children (i.e. children before the traversal but after the current size)
@ -185,7 +185,7 @@ namespace blobstore {
[] (uint32_t /*index*/)->Data {ASSERT(false, "We're only creating gap leaves here, not traversing any.");},
[] (DataInnerNode* /*node*/) {});
ASSERT(child->depth() == depth-1, "Created child node has wrong depth");
children.push_back(child->key());
children.push_back(child->blockId());
}
// Create new children that are traversed
for(uint32_t childIndex = beginChild; childIndex < endChild; ++childIndex) {
@ -194,7 +194,7 @@ namespace blobstore {
uint32_t localEndIndex = std::min(leavesPerChild, endIndex - childOffset);
auto child = _createNewSubtree(localBeginIndex, localEndIndex, leafOffset + childOffset, depth - 1, onCreateLeaf, onBacktrackFromSubtree);
ASSERT(child->depth() == depth-1, "Created child node has wrong depth");
children.push_back(child->key());
children.push_back(child->blockId());
}
ASSERT(children.size() > 0, "No children created");
@ -221,7 +221,7 @@ namespace blobstore {
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) {
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
if (inner != nullptr && inner->numChildren() == 1) {
auto newRoot = _whileRootHasOnlyOneChildRemoveRootReturnChild(inner->getChild(0)->key());
auto newRoot = _whileRootHasOnlyOneChildRemoveRootReturnChild(inner->getChild(0)->blockId());
auto result = _nodeStore->overwriteNodeWith(std::move(root), *newRoot);
_nodeStore->remove(std::move(newRoot));
return result;
@ -230,14 +230,14 @@ namespace blobstore {
}
}
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::Key &key) {
auto current = _nodeStore->load(key);
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::BlockId &blockId) {
auto current = _nodeStore->load(blockId);
ASSERT(current != none, "Node not found");
auto inner = dynamic_pointer_move<DataInnerNode>(*current);
if (inner == none) {
return std::move(*current);
} else if ((*inner)->numChildren() == 1) {
auto result = _whileRootHasOnlyOneChildRemoveRootReturnChild((*inner)->getChild(0)->key());
auto result = _whileRootHasOnlyOneChildRemoveRootReturnChild((*inner)->getChild(0)->blockId());
_nodeStore->remove(std::move(*inner));
return result;
} else {

View File

@ -5,7 +5,7 @@
#include <cpp-utils/macros.h>
#include <cpp-utils/pointer/unique_ref.h>
#include <cpp-utils/data/Data.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include "blobstore/implementations/onblocks/datatreestore/LeafHandle.h"
namespace blobstore {
@ -45,7 +45,7 @@ namespace blobstore {
std::function<void (uint32_t index, bool isRightBorderLeaf, LeafHandle leaf)> onExistingLeaf,
std::function<cpputils::Data (uint32_t index)> onCreateLeaf,
std::function<void (datanodestore::DataInnerNode *node)> onBacktrackFromSubtree);
void _traverseExistingSubtree(const blockstore::Key &key, uint8_t depth, uint32_t beginIndex, uint32_t endIndex, uint32_t leafOffset, bool isLeftBorderOfTraversal, bool isRightBorderNode, bool growLastLeaf,
void _traverseExistingSubtree(const blockstore::BlockId &blockId, uint8_t depth, uint32_t beginIndex, uint32_t endIndex, uint32_t leafOffset, bool isLeftBorderOfTraversal, bool isRightBorderNode, bool growLastLeaf,
std::function<void (uint32_t index, bool isRightBorderLeaf, LeafHandle leaf)> onExistingLeaf,
std::function<cpputils::Data (uint32_t index)> onCreateLeaf,
std::function<void (datanodestore::DataInnerNode *node)> onBacktrackFromSubtree);
@ -56,7 +56,7 @@ namespace blobstore {
uint32_t _maxLeavesForTreeDepth(uint8_t depth) const;
std::function<cpputils::Data (uint32_t index)> _createMaxSizeLeaf() const;
cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildReplaceRootWithItsChild(cpputils::unique_ref<datanodestore::DataNode> root);
cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::Key &key);
cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::BlockId &blockId);
DISALLOW_COPY_AND_ASSIGN(LeafTraverser);
};

View File

@ -1,6 +1,6 @@
#include "algorithms.h"
#include <cpp-utils/pointer/cast.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include "../../datanodestore/DataInnerNode.h"
#include "../../datanodestore/DataNodeStore.h"
@ -13,7 +13,7 @@ using cpputils::unique_ref;
using blobstore::onblocks::datanodestore::DataInnerNode;
using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataNodeStore;
using blockstore::Key;
using blockstore::BlockId;
using boost::optional;
using boost::none;
@ -23,8 +23,8 @@ namespace datatreestore {
namespace algorithms {
optional<unique_ref<DataInnerNode>> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
Key key = node.LastChild()->key();
auto lastChild = nodeStore->load(key);
BlockId blockId = node.LastChild()->blockId();
auto lastChild = nodeStore->load(blockId);
ASSERT(lastChild != none, "Couldn't load last child");
return dynamic_pointer_move<DataInnerNode>(*lastChild);
}

View File

@ -10,12 +10,12 @@ namespace blobstore {
namespace onblocks {
namespace parallelaccessdatatreestore {
class DataTreeRef final: public parallelaccessstore::ParallelAccessStore<datatreestore::DataTree, DataTreeRef, blockstore::Key>::ResourceRefBase {
class DataTreeRef final: public parallelaccessstore::ParallelAccessStore<datatreestore::DataTree, DataTreeRef, blockstore::BlockId>::ResourceRefBase {
public:
DataTreeRef(datatreestore::DataTree *baseTree): _baseTree(baseTree) {}
const blockstore::Key &key() const {
return _baseTree->key();
const blockstore::BlockId &blockId() const {
return _baseTree->blockId();
}
uint64_t maxBytesPerLeaf() const {

View File

@ -9,7 +9,7 @@ using cpputils::make_unique_ref;
using boost::optional;
using blobstore::onblocks::datatreestore::DataTreeStore;
using blockstore::Key;
using blockstore::BlockId;
namespace blobstore {
namespace onblocks {
@ -26,23 +26,23 @@ ParallelAccessDataTreeStore::ParallelAccessDataTreeStore(unique_ref<DataTreeStor
ParallelAccessDataTreeStore::~ParallelAccessDataTreeStore() {
}
optional<unique_ref<DataTreeRef>> ParallelAccessDataTreeStore::load(const blockstore::Key &key) {
return _parallelAccessStore.load(key);
optional<unique_ref<DataTreeRef>> ParallelAccessDataTreeStore::load(const blockstore::BlockId &blockId) {
return _parallelAccessStore.load(blockId);
}
unique_ref<DataTreeRef> ParallelAccessDataTreeStore::createNewTree() {
auto dataTree = _dataTreeStore->createNewTree();
Key key = dataTree->key();
return _parallelAccessStore.add(key, std::move(dataTree));
BlockId blockId = dataTree->blockId();
return _parallelAccessStore.add(blockId, std::move(dataTree));
}
void ParallelAccessDataTreeStore::remove(unique_ref<DataTreeRef> tree) {
Key key = tree->key();
return _parallelAccessStore.remove(key, std::move(tree));
BlockId blockId = tree->blockId();
return _parallelAccessStore.remove(blockId, std::move(tree));
}
void ParallelAccessDataTreeStore::remove(const Key &key) {
return _parallelAccessStore.remove(key);
void ParallelAccessDataTreeStore::remove(const BlockId &blockId) {
return _parallelAccessStore.remove(blockId);
}

View File

@ -4,7 +4,7 @@
#include <memory>
#include <cpp-utils/macros.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <parallelaccessstore/ParallelAccessStore.h>
#include "../datatreestore/DataTreeStore.h"
@ -20,12 +20,12 @@ public:
ParallelAccessDataTreeStore(cpputils::unique_ref<datatreestore::DataTreeStore> dataTreeStore);
~ParallelAccessDataTreeStore();
boost::optional<cpputils::unique_ref<DataTreeRef>> load(const blockstore::Key &key);
boost::optional<cpputils::unique_ref<DataTreeRef>> load(const blockstore::BlockId &blockId);
cpputils::unique_ref<DataTreeRef> createNewTree();
void remove(cpputils::unique_ref<DataTreeRef> tree);
void remove(const blockstore::Key &key);
void remove(const blockstore::BlockId &blockId);
//TODO Test blocksizeBytes/numBlocks/estimateSpaceForNumBlocksLeft
uint64_t virtualBlocksizeBytes() const;
@ -34,7 +34,7 @@ public:
private:
cpputils::unique_ref<datatreestore::DataTreeStore> _dataTreeStore;
parallelaccessstore::ParallelAccessStore<datatreestore::DataTree, DataTreeRef, blockstore::Key> _parallelAccessStore;
parallelaccessstore::ParallelAccessStore<datatreestore::DataTree, DataTreeRef, blockstore::BlockId> _parallelAccessStore;
DISALLOW_COPY_AND_ASSIGN(ParallelAccessDataTreeStore);
};

View File

@ -11,22 +11,22 @@ namespace blobstore {
namespace onblocks {
namespace parallelaccessdatatreestore {
class ParallelAccessDataTreeStoreAdapter final: public parallelaccessstore::ParallelAccessBaseStore<datatreestore::DataTree, blockstore::Key> {
class ParallelAccessDataTreeStoreAdapter final: public parallelaccessstore::ParallelAccessBaseStore<datatreestore::DataTree, blockstore::BlockId> {
public:
ParallelAccessDataTreeStoreAdapter(datatreestore::DataTreeStore *baseDataTreeStore)
:_baseDataTreeStore(std::move(baseDataTreeStore)) {
}
boost::optional<cpputils::unique_ref<datatreestore::DataTree>> loadFromBaseStore(const blockstore::Key &key) override {
return _baseDataTreeStore->load(key);
boost::optional<cpputils::unique_ref<datatreestore::DataTree>> loadFromBaseStore(const blockstore::BlockId &blockId) override {
return _baseDataTreeStore->load(blockId);
}
void removeFromBaseStore(cpputils::unique_ref<datatreestore::DataTree> dataTree) override {
return _baseDataTreeStore->remove(std::move(dataTree));
}
void removeFromBaseStore(const blockstore::Key &key) override {
return _baseDataTreeStore->remove(key);
void removeFromBaseStore(const blockstore::BlockId &blockId) override {
return _baseDataTreeStore->remove(blockId);
}
private:

View File

@ -4,7 +4,7 @@
#include <cstring>
#include <cstdint>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <cpp-utils/data/Data.h>
namespace blobstore {
@ -13,8 +13,8 @@ class Blob {
public:
virtual ~Blob() {}
//TODO Use own Key class for blobstore
virtual const blockstore::Key &key() const = 0;
//TODO Use own Id class for blobstore
virtual const blockstore::BlockId &blockId() const = 0;
virtual uint64_t size() const = 0;
virtual void resize(uint64_t numBytes) = 0;

View File

@ -6,7 +6,7 @@
#include <string>
#include <memory>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <cpp-utils/pointer/unique_ref.h>
namespace blobstore {
@ -17,9 +17,9 @@ public:
virtual ~BlobStore() {}
virtual cpputils::unique_ref<Blob> create() = 0;
virtual boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::Key &key) = 0;
virtual boost::optional<cpputils::unique_ref<Blob>> load(const blockstore::BlockId &blockId) = 0;
virtual void remove(cpputils::unique_ref<Blob> blob) = 0;
virtual void remove(const blockstore::Key &key) = 0;
virtual void remove(const blockstore::BlockId &blockId) = 0;
virtual uint64_t numBlocks() const = 0;
virtual uint64_t estimateSpaceForNumBlocksLeft() const = 0;

View File

@ -1,7 +1,7 @@
project (blockstore)
set(SOURCES
utils/Key.cpp
utils/BlockId.cpp
utils/IdWrapper.cpp
utils/BlockStoreUtils.cpp
utils/FileDoesntExistException.cpp
@ -27,7 +27,7 @@ set(SOURCES
implementations/low2highlevel/LowToHighLevelBlockStore.cpp
implementations/integrity/IntegrityBlockStore2.cpp
implementations/integrity/KnownBlockVersions.cpp
implementations/integrity/ClientIdAndBlockKey.cpp
implementations/integrity/ClientIdAndBlockId.cpp
implementations/integrity/IntegrityViolationError.cpp
implementations/mock/MockBlockStore.cpp
implementations/mock/MockBlock.cpp

View File

@ -22,17 +22,17 @@ using std::mutex;
namespace blockstore {
namespace caching {
CachingBlockStore2::CachedBlock::CachedBlock(const CachingBlockStore2* blockStore, const Key& key, cpputils::Data data, bool isDirty)
: _blockStore(blockStore), _key(key), _data(std::move(data)), _dirty(isDirty) {
CachingBlockStore2::CachedBlock::CachedBlock(const CachingBlockStore2* blockStore, const BlockId &blockId, cpputils::Data data, bool isDirty)
: _blockStore(blockStore), _blockId(blockId), _data(std::move(data)), _dirty(isDirty) {
}
CachingBlockStore2::CachedBlock::~CachedBlock() {
if (_dirty) {
_blockStore->_baseBlockStore->store(_key, _data);
_blockStore->_baseBlockStore->store(_blockId, _data);
}
// remove it from the list of blocks not in the base store, if it's on it
unique_lock<mutex> lock(_blockStore->_cachedBlocksNotInBaseStoreMutex);
_blockStore->_cachedBlocksNotInBaseStore.erase(_key);
_blockStore->_cachedBlocksNotInBaseStore.erase(_blockId);
}
const Data& CachingBlockStore2::CachedBlock::read() const {
@ -52,30 +52,30 @@ CachingBlockStore2::CachingBlockStore2(cpputils::unique_ref<BlockStore2> baseBlo
: _baseBlockStore(std::move(baseBlockStore)), _cachedBlocksNotInBaseStoreMutex(), _cachedBlocksNotInBaseStore(), _cache() {
}
bool CachingBlockStore2::tryCreate(const Key &key, const Data &data) {
bool CachingBlockStore2::tryCreate(const BlockId &blockId, const Data &data) {
//TODO Check if block exists in base store? Performance hit? It's very unlikely it exists.
auto popped = _cache.pop(key);
auto popped = _cache.pop(blockId);
if (popped != boost::none) {
// entry already exists in cache
_cache.push(key, std::move(*popped)); // push the just popped element back to the cache
_cache.push(blockId, std::move(*popped)); // push the just popped element back to the cache
return false;
} else {
_cache.push(key, make_unique_ref<CachingBlockStore2::CachedBlock>(this, key, data.copy(), true));
_cache.push(blockId, make_unique_ref<CachingBlockStore2::CachedBlock>(this, blockId, data.copy(), true));
unique_lock<mutex> lock(_cachedBlocksNotInBaseStoreMutex);
_cachedBlocksNotInBaseStore.insert(key);
_cachedBlocksNotInBaseStore.insert(blockId);
return true;
}
}
bool CachingBlockStore2::remove(const Key &key) {
bool CachingBlockStore2::remove(const BlockId &blockId) {
// TODO Don't write-through but cache remove operations
auto popped = _cache.pop(key);
auto popped = _cache.pop(blockId);
if (popped != boost::none) {
// Remove from base store if it exists in the base store
{
unique_lock<mutex> lock(_cachedBlocksNotInBaseStoreMutex);
if (_cachedBlocksNotInBaseStore.count(key) == 0) {
const bool existedInBaseStore = _baseBlockStore->remove(key);
if (_cachedBlocksNotInBaseStore.count(blockId) == 0) {
const bool existedInBaseStore = _baseBlockStore->remove(blockId);
if (!existedInBaseStore) {
throw std::runtime_error("Tried to remove block. Block existed in cache and stated it exists in base store, but wasn't found there.");
}
@ -85,45 +85,45 @@ bool CachingBlockStore2::remove(const Key &key) {
std::move(**popped).markNotDirty();
return true;
} else {
return _baseBlockStore->remove(key);
return _baseBlockStore->remove(blockId);
}
}
optional<unique_ref<CachingBlockStore2::CachedBlock>> CachingBlockStore2::_loadFromCacheOrBaseStore(const Key &key) const {
auto popped = _cache.pop(key);
optional<unique_ref<CachingBlockStore2::CachedBlock>> CachingBlockStore2::_loadFromCacheOrBaseStore(const BlockId &blockId) const {
auto popped = _cache.pop(blockId);
if (popped != boost::none) {
return std::move(*popped);
} else {
auto loaded = _baseBlockStore->load(key);
auto loaded = _baseBlockStore->load(blockId);
if (loaded == boost::none) {
return boost::none;
}
return make_unique_ref<CachingBlockStore2::CachedBlock>(this, key, std::move(*loaded), false);
return make_unique_ref<CachingBlockStore2::CachedBlock>(this, blockId, std::move(*loaded), false);
}
}
optional<Data> CachingBlockStore2::load(const Key &key) const {
auto loaded = _loadFromCacheOrBaseStore(key);
optional<Data> CachingBlockStore2::load(const BlockId &blockId) const {
auto loaded = _loadFromCacheOrBaseStore(blockId);
if (loaded == boost::none) {
// TODO Cache non-existence?
return boost::none;
}
optional<Data> result = (*loaded)->read().copy();
_cache.push(key, std::move(*loaded));
_cache.push(blockId, std::move(*loaded));
return result;
}
void CachingBlockStore2::store(const Key &key, const Data &data) {
auto popped = _cache.pop(key);
void CachingBlockStore2::store(const BlockId &blockId, const Data &data) {
auto popped = _cache.pop(blockId);
if (popped != boost::none) {
(*popped)->write(data.copy());
} else {
popped = make_unique_ref<CachingBlockStore2::CachedBlock>(this, key, data.copy(), false);
popped = make_unique_ref<CachingBlockStore2::CachedBlock>(this, blockId, data.copy(), false);
// TODO Instead of storing it to the base store, we could just keep it dirty in the cache
// and (if it doesn't exist in base store yet) add it to _cachedBlocksNotInBaseStore
_baseBlockStore->store(key, data);
_baseBlockStore->store(blockId, data);
}
_cache.push(key, std::move(*popped));
_cache.push(blockId, std::move(*popped));
}
uint64_t CachingBlockStore2::numBlocks() const {
@ -143,11 +143,11 @@ uint64_t CachingBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize)
return _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
}
void CachingBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
void CachingBlockStore2::forEachBlock(std::function<void (const BlockId &)> callback) const {
{
unique_lock<mutex> lock(_cachedBlocksNotInBaseStoreMutex);
for (const Key &key : _cachedBlocksNotInBaseStore) {
callback(key);
for (const BlockId &blockId : _cachedBlocksNotInBaseStore) {
callback(blockId);
}
}
_baseBlockStore->forEachBlock(std::move(callback));

View File

@ -14,14 +14,14 @@ class CachingBlockStore2 final: public BlockStore2 {
public:
CachingBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore);
bool tryCreate(const Key &key, const cpputils::Data &data) override;
bool remove(const Key &key) override;
boost::optional<cpputils::Data> load(const Key &key) const override;
void store(const Key &key, const cpputils::Data &data) override;
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
void flush();
@ -29,7 +29,7 @@ private:
// TODO Is a cache implementation with onEvict callback instead of destructor simpler?
class CachedBlock final {
public:
CachedBlock(const CachingBlockStore2* blockStore, const Key& key, cpputils::Data data, bool isDirty);
CachedBlock(const CachingBlockStore2* blockStore, const BlockId &blockId, cpputils::Data data, bool isDirty);
~CachedBlock();
const cpputils::Data& read() const;
@ -37,22 +37,22 @@ private:
void markNotDirty() &&; // only on rvalue because the destructor should be called after calling markNotDirty(). It shouldn't be put back into the cache.
private:
const CachingBlockStore2* _blockStore;
Key _key;
BlockId _blockId;
cpputils::Data _data;
bool _dirty;
DISALLOW_COPY_AND_ASSIGN(CachedBlock);
};
boost::optional<cpputils::unique_ref<CachedBlock>> _loadFromCacheOrBaseStore(const Key &key) const;
boost::optional<cpputils::unique_ref<CachedBlock>> _loadFromCacheOrBaseStore(const BlockId &blockId) const;
cpputils::unique_ref<BlockStore2> _baseBlockStore;
friend class CachedBlock;
// TODO Store CachedBlock directly, without unique_ref
mutable std::mutex _cachedBlocksNotInBaseStoreMutex;
mutable std::unordered_set<Key> _cachedBlocksNotInBaseStore;
mutable Cache<Key, cpputils::unique_ref<CachedBlock>, 1000> _cache;
mutable std::unordered_set<BlockId> _cachedBlocksNotInBaseStore;
mutable Cache<BlockId, cpputils::unique_ref<CachedBlock>, 1000> _cache;
DISALLOW_COPY_AND_ASSIGN(CachingBlockStore2);
};

View File

@ -18,8 +18,8 @@ template<class Compressor> class CompressingBlockStore;
template<class Compressor>
class CompressedBlock final: public Block {
public:
static boost::optional<cpputils::unique_ref<CompressedBlock>> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data decompressedData);
static cpputils::unique_ref<CompressedBlock> Overwrite(BlockStore *baseBlockStore, const Key &key, cpputils::Data decompressedData);
static boost::optional<cpputils::unique_ref<CompressedBlock>> TryCreateNew(BlockStore *baseBlockStore, const BlockId &blockId, cpputils::Data decompressedData);
static cpputils::unique_ref<CompressedBlock> Overwrite(BlockStore *baseBlockStore, const BlockId &blockId, cpputils::Data decompressedData);
static cpputils::unique_ref<CompressedBlock> Decompress(cpputils::unique_ref<Block> baseBlock);
CompressedBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data decompressedData);
@ -47,9 +47,9 @@ private:
};
template<class Compressor>
boost::optional<cpputils::unique_ref<CompressedBlock<Compressor>>> CompressedBlock<Compressor>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data decompressedData) {
boost::optional<cpputils::unique_ref<CompressedBlock<Compressor>>> CompressedBlock<Compressor>::TryCreateNew(BlockStore *baseBlockStore, const BlockId &blockId, cpputils::Data decompressedData) {
cpputils::Data compressed = Compressor::Compress(decompressedData);
auto baseBlock = baseBlockStore->tryCreate(key, std::move(compressed));
auto baseBlock = baseBlockStore->tryCreate(blockId, std::move(compressed));
if (baseBlock == boost::none) {
//TODO Test this code branch
return boost::none;
@ -59,9 +59,9 @@ boost::optional<cpputils::unique_ref<CompressedBlock<Compressor>>> CompressedBlo
}
template<class Compressor>
cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::Overwrite(BlockStore *baseBlockStore, const Key &key, cpputils::Data decompressedData) {
cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::Overwrite(BlockStore *baseBlockStore, const BlockId &blockId, cpputils::Data decompressedData) {
cpputils::Data compressed = Compressor::Compress(decompressedData);
auto baseBlock = baseBlockStore->overwrite(key, std::move(compressed));
auto baseBlock = baseBlockStore->overwrite(blockId, std::move(compressed));
return cpputils::make_unique_ref<CompressedBlock<Compressor>>(std::move(baseBlock), std::move(decompressedData));
}
@ -74,7 +74,7 @@ cpputils::unique_ref<CompressedBlock<Compressor>> CompressedBlock<Compressor>::D
template<class Compressor>
CompressedBlock<Compressor>::CompressedBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data decompressedData)
: Block(baseBlock->key()),
: Block(baseBlock->blockId()),
_baseBlock(std::move(baseBlock)),
_decompressedData(std::move(decompressedData)),
_dataChanged(false) {

View File

@ -14,15 +14,15 @@ public:
CompressingBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore);
~CompressingBlockStore();
Key createKey() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const Key &key) override;
cpputils::unique_ref<Block> overwrite(const blockstore::Key &key, cpputils::Data data) override;
void remove(const Key &key) override;
BlockId createBlockId() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) override;
cpputils::unique_ref<Block> overwrite(const blockstore::BlockId &blockId, cpputils::Data data) override;
void remove(const BlockId &blockId) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
cpputils::unique_ref<BlockStore> _baseBlockStore;
@ -40,13 +40,13 @@ CompressingBlockStore<Compressor>::~CompressingBlockStore() {
}
template<class Compressor>
Key CompressingBlockStore<Compressor>::createKey() {
return _baseBlockStore->createKey();
BlockId CompressingBlockStore<Compressor>::createBlockId() {
return _baseBlockStore->createBlockId();
}
template<class Compressor>
boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::tryCreate(const Key &key, cpputils::Data data) {
auto result = CompressedBlock<Compressor>::TryCreateNew(_baseBlockStore.get(), key, std::move(data));
boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::tryCreate(const BlockId &blockId, cpputils::Data data) {
auto result = CompressedBlock<Compressor>::TryCreateNew(_baseBlockStore.get(), blockId, std::move(data));
if (result == boost::none) {
return boost::none;
}
@ -54,13 +54,13 @@ boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::
}
template<class Compressor>
cpputils::unique_ref<Block> CompressingBlockStore<Compressor>::overwrite(const blockstore::Key &key, cpputils::Data data) {
return CompressedBlock<Compressor>::Overwrite(_baseBlockStore.get(), key, std::move(data));
cpputils::unique_ref<Block> CompressingBlockStore<Compressor>::overwrite(const blockstore::BlockId &blockId, cpputils::Data data) {
return CompressedBlock<Compressor>::Overwrite(_baseBlockStore.get(), blockId, std::move(data));
}
template<class Compressor>
boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::load(const Key &key) {
auto loaded = _baseBlockStore->load(key);
boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::load(const BlockId &blockId) {
auto loaded = _baseBlockStore->load(blockId);
if (loaded == boost::none) {
return boost::none;
}
@ -68,8 +68,8 @@ boost::optional<cpputils::unique_ref<Block>> CompressingBlockStore<Compressor>::
}
template<class Compressor>
void CompressingBlockStore<Compressor>::remove(const Key &key) {
return _baseBlockStore->remove(key);
void CompressingBlockStore<Compressor>::remove(const BlockId &blockId) {
return _baseBlockStore->remove(blockId);
}
template<class Compressor>
@ -83,7 +83,7 @@ uint64_t CompressingBlockStore<Compressor>::estimateNumFreeBytes() const {
}
template<class Compressor>
void CompressingBlockStore<Compressor>::forEachBlock(std::function<void (const Key &)> callback) const {
void CompressingBlockStore<Compressor>::forEachBlock(std::function<void (const BlockId &)> callback) const {
return _baseBlockStore->forEachBlock(callback);
}

View File

@ -19,14 +19,14 @@ public:
EncryptedBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore, const typename Cipher::EncryptionKey &encKey);
bool tryCreate(const Key &key, const cpputils::Data &data) override;
bool remove(const Key &key) override;
boost::optional<cpputils::Data> load(const Key &key) const override;
void store(const Key &key, const cpputils::Data &data) override;
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
//This function should only be used by test cases
void __setKey(const typename Cipher::EncryptionKey &encKey);
@ -40,11 +40,11 @@ private:
static constexpr uint16_t FORMAT_VERSION_HEADER = 1;
cpputils::Data _encrypt(const cpputils::Data &data) const;
boost::optional<cpputils::Data> _tryDecrypt(const Key &key, const cpputils::Data &data) const;
boost::optional<cpputils::Data> _tryDecrypt(const BlockId &blockId, const cpputils::Data &data) const;
static cpputils::Data _prependFormatHeaderToData(const cpputils::Data &data);
#ifndef CRYFS_NO_COMPATIBILITY
static bool _keyHeaderIsCorrect(const Key &key, const cpputils::Data &data);
static bool _blockIdHeaderIsCorrect(const BlockId &blockId, const cpputils::Data &data);
static cpputils::Data _migrateBlock(const cpputils::Data &data);
#endif
static void _checkFormatHeader(const cpputils::Data &data);
@ -70,30 +70,30 @@ inline EncryptedBlockStore2<Cipher>::EncryptedBlockStore2(cpputils::unique_ref<B
}
template<class Cipher>
inline bool EncryptedBlockStore2<Cipher>::tryCreate(const Key &key, const cpputils::Data &data) {
inline bool EncryptedBlockStore2<Cipher>::tryCreate(const BlockId &blockId, const cpputils::Data &data) {
cpputils::Data encrypted = _encrypt(data);
return _baseBlockStore->tryCreate(key, encrypted);
return _baseBlockStore->tryCreate(blockId, encrypted);
}
template<class Cipher>
inline bool EncryptedBlockStore2<Cipher>::remove(const Key &key) {
return _baseBlockStore->remove(key);
inline bool EncryptedBlockStore2<Cipher>::remove(const BlockId &blockId) {
return _baseBlockStore->remove(blockId);
}
template<class Cipher>
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::load(const Key &key) const {
auto loaded = _baseBlockStore->load(key);
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::load(const BlockId &blockId) const {
auto loaded = _baseBlockStore->load(blockId);
if (boost::none == loaded) {
return boost::optional<cpputils::Data>(boost::none);
}
return _tryDecrypt(key, *loaded);
return _tryDecrypt(blockId, *loaded);
}
template<class Cipher>
inline void EncryptedBlockStore2<Cipher>::store(const Key &key, const cpputils::Data &data) {
inline void EncryptedBlockStore2<Cipher>::store(const BlockId &blockId, const cpputils::Data &data) {
cpputils::Data encrypted = _encrypt(data);
return _baseBlockStore->store(key, encrypted);
return _baseBlockStore->store(blockId, encrypted);
}
template<class Cipher>
@ -116,7 +116,7 @@ inline uint64_t EncryptedBlockStore2<Cipher>::blockSizeFromPhysicalBlockSize(uin
}
template<class Cipher>
inline void EncryptedBlockStore2<Cipher>::forEachBlock(std::function<void (const Key &)> callback) const {
inline void EncryptedBlockStore2<Cipher>::forEachBlock(std::function<void (const BlockId &)> callback) const {
return _baseBlockStore->forEachBlock(std::move(callback));
}
@ -127,7 +127,7 @@ inline cpputils::Data EncryptedBlockStore2<Cipher>::_encrypt(const cpputils::Dat
}
template<class Cipher>
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt(const Key &key, const cpputils::Data &data) const {
inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt(const BlockId &blockId, const cpputils::Data &data) const {
_checkFormatHeader(data);
boost::optional<cpputils::Data> decrypted = Cipher::decrypt((CryptoPP::byte*)data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER), _encKey);
if (decrypted == boost::none) {
@ -137,7 +137,7 @@ inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt
#ifndef CRYFS_NO_COMPATIBILITY
if (FORMAT_VERSION_HEADER_OLD == _readFormatHeader(data)) {
if (!_keyHeaderIsCorrect(key, *decrypted)) {
if (!_blockIdHeaderIsCorrect(blockId, *decrypted)) {
return boost::none;
}
*decrypted = _migrateBlock(*decrypted);
@ -152,12 +152,12 @@ inline boost::optional<cpputils::Data> EncryptedBlockStore2<Cipher>::_tryDecrypt
#ifndef CRYFS_NO_COMPATIBILITY
template<class Cipher>
inline cpputils::Data EncryptedBlockStore2<Cipher>::_migrateBlock(const cpputils::Data &data) {
return data.copyAndRemovePrefix(Key::BINARY_LENGTH);
return data.copyAndRemovePrefix(BlockId::BINARY_LENGTH);
}
template<class Cipher>
inline bool EncryptedBlockStore2<Cipher>::_keyHeaderIsCorrect(const Key &key, const cpputils::Data &data) {
return key == Key::FromBinary(data.data());
inline bool EncryptedBlockStore2<Cipher>::_blockIdHeaderIsCorrect(const BlockId &blockId, const cpputils::Data &data) {
return blockId == BlockId::FromBinary(data.data());
}
#endif

View File

@ -23,21 +23,21 @@ namespace inmemory {
InMemoryBlockStore2::InMemoryBlockStore2()
: _blocks() {}
bool InMemoryBlockStore2::tryCreate(const Key &key, const Data &data) {
bool InMemoryBlockStore2::tryCreate(const BlockId &blockId, const Data &data) {
std::unique_lock<std::mutex> lock(_mutex);
return _tryCreate(key, data);
return _tryCreate(blockId, data);
}
bool InMemoryBlockStore2::_tryCreate(const Key &key, const Data &data) {
auto result = _blocks.insert(make_pair(key, data.copy()));
return result.second; // Return if insertion was successful (i.e. key didn't exist yet)
bool InMemoryBlockStore2::_tryCreate(const BlockId &blockId, const Data &data) {
auto result = _blocks.insert(make_pair(blockId, data.copy()));
return result.second; // Return if insertion was successful (i.e. blockId didn't exist yet)
}
bool InMemoryBlockStore2::remove(const Key &key) {
bool InMemoryBlockStore2::remove(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
auto found = _blocks.find(key);
auto found = _blocks.find(blockId);
if (found == _blocks.end()) {
// Key not found
// BlockId not found
return false;
}
@ -45,20 +45,20 @@ bool InMemoryBlockStore2::remove(const Key &key) {
return true;
}
optional<Data> InMemoryBlockStore2::load(const Key &key) const {
optional<Data> InMemoryBlockStore2::load(const BlockId &blockId) const {
std::unique_lock<std::mutex> lock(_mutex);
auto found = _blocks.find(key);
auto found = _blocks.find(blockId);
if (found == _blocks.end()) {
return boost::none;
}
return found->second.copy();
}
void InMemoryBlockStore2::store(const Key &key, const Data &data) {
void InMemoryBlockStore2::store(const BlockId &blockId, const Data &data) {
std::unique_lock<std::mutex> lock(_mutex);
auto found = _blocks.find(key);
auto found = _blocks.find(blockId);
if (found == _blocks.end()) {
bool success = _tryCreate(key, data);
bool success = _tryCreate(blockId, data);
if (!success) {
throw std::runtime_error("Could neither save nor create the block in InMemoryBlockStore::store()");
}
@ -81,9 +81,9 @@ uint64_t InMemoryBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize)
return blockSize;
}
vector<Key> InMemoryBlockStore2::_allBlockKeys() const {
vector<BlockId> InMemoryBlockStore2::_allBlockIds() const {
std::unique_lock<std::mutex> lock(_mutex);
vector<Key> result;
vector<BlockId> result;
result.reserve(_blocks.size());
for (const auto &entry : _blocks) {
result.push_back(entry.first);
@ -91,10 +91,10 @@ vector<Key> InMemoryBlockStore2::_allBlockKeys() const {
return result;
}
void InMemoryBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
auto keys = _allBlockKeys();
for (const auto &key : keys) {
callback(key);
void InMemoryBlockStore2::forEachBlock(std::function<void (const BlockId &)> callback) const {
auto blockIds = _allBlockIds();
for (const auto &blockId : blockIds) {
callback(blockId);
}
}

View File

@ -13,20 +13,20 @@ class InMemoryBlockStore2 final: public BlockStore2 {
public:
InMemoryBlockStore2();
bool tryCreate(const Key &key, const cpputils::Data &data) override;
bool remove(const Key &key) override;
boost::optional<cpputils::Data> load(const Key &key) const override;
void store(const Key &key, const cpputils::Data &data) override;
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
std::vector<Key> _allBlockKeys() const;
bool _tryCreate(const Key &key, const cpputils::Data &data);
std::vector<BlockId> _allBlockIds() const;
bool _tryCreate(const BlockId &blockId, const cpputils::Data &data);
std::unordered_map<Key, cpputils::Data> _blocks;
std::unordered_map<BlockId, cpputils::Data> _blocks;
mutable std::mutex _mutex;
DISALLOW_COPY_AND_ASSIGN(InMemoryBlockStore2);

View File

@ -0,0 +1 @@
#include "ClientIdAndBlockId.h"

View File

@ -1,16 +1,16 @@
#pragma once
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKKEY_H_
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKKEY_H_
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKID_H_
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_CLIENTIDANDBLOCKID_H_
#include <utility>
#include "../../utils/Key.h"
#include "blockstore/utils/BlockId.h"
namespace blockstore {
namespace integrity {
struct ClientIdAndBlockKey {
struct ClientIdAndBlockId {
uint32_t clientId;
Key blockKey;
BlockId blockId;
};
}
@ -18,15 +18,15 @@ namespace blockstore {
// Allow using it in std::unordered_set / std::unordered_map
namespace std {
template<> struct hash<blockstore::integrity::ClientIdAndBlockKey> {
size_t operator()(const blockstore::integrity::ClientIdAndBlockKey &ref) const {
return std::hash<uint32_t>()(ref.clientId) ^ std::hash<blockstore::Key>()(ref.blockKey);
template<> struct hash<blockstore::integrity::ClientIdAndBlockId> {
size_t operator()(const blockstore::integrity::ClientIdAndBlockId &ref) const {
return std::hash<uint32_t>()(ref.clientId) ^ std::hash<blockstore::BlockId>()(ref.blockId);
}
};
template<> struct equal_to<blockstore::integrity::ClientIdAndBlockKey> {
size_t operator()(const blockstore::integrity::ClientIdAndBlockKey &lhs, const blockstore::integrity::ClientIdAndBlockKey &rhs) const {
return lhs.clientId == rhs.clientId && lhs.blockKey == rhs.blockKey;
template<> struct equal_to<blockstore::integrity::ClientIdAndBlockId> {
size_t operator()(const blockstore::integrity::ClientIdAndBlockId &lhs, const blockstore::integrity::ClientIdAndBlockId &rhs) const {
return lhs.clientId == rhs.clientId && lhs.blockId == rhs.blockId;
}
};
}

View File

@ -1 +0,0 @@
#include "ClientIdAndBlockKey.h"

View File

@ -22,21 +22,21 @@ constexpr unsigned int IntegrityBlockStore2::CLIENTID_HEADER_OFFSET;
constexpr unsigned int IntegrityBlockStore2::VERSION_HEADER_OFFSET;
constexpr unsigned int IntegrityBlockStore2::HEADER_LENGTH;
Data IntegrityBlockStore2::_prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const Data &data) {
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + Key::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length");
Data IntegrityBlockStore2::_prependHeaderToData(const BlockId& blockId, uint32_t myClientId, uint64_t version, const Data &data) {
static_assert(HEADER_LENGTH == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + sizeof(myClientId) + sizeof(version), "Wrong header length");
Data result(data.size() + HEADER_LENGTH);
std::memcpy(result.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
std::memcpy(result.dataOffset(ID_HEADER_OFFSET), key.data().data(), Key::BINARY_LENGTH);
std::memcpy(result.dataOffset(ID_HEADER_OFFSET), blockId.data().data(), BlockId::BINARY_LENGTH);
std::memcpy(result.dataOffset(CLIENTID_HEADER_OFFSET), &myClientId, sizeof(myClientId));
std::memcpy(result.dataOffset(VERSION_HEADER_OFFSET), &version, sizeof(version));
std::memcpy((uint8_t*)result.dataOffset(HEADER_LENGTH), data.data(), data.size());
return result;
}
void IntegrityBlockStore2::_checkHeader(const Key &key, const Data &data) const {
void IntegrityBlockStore2::_checkHeader(const BlockId &blockId, const Data &data) const {
_checkFormatHeader(data);
_checkIdHeader(key, data);
_checkVersionHeader(key, data);
_checkIdHeader(blockId, data);
_checkVersionHeader(blockId, data);
}
void IntegrityBlockStore2::_checkFormatHeader(const Data &data) const {
@ -45,19 +45,19 @@ void IntegrityBlockStore2::_checkFormatHeader(const Data &data) const {
}
}
void IntegrityBlockStore2::_checkVersionHeader(const Key &key, const Data &data) const {
void IntegrityBlockStore2::_checkVersionHeader(const BlockId &blockId, const Data &data) const {
uint32_t clientId = _readClientId(data);
uint64_t version = _readVersion(data);
if(!_knownBlockVersions.checkAndUpdateVersion(clientId, key, version)) {
if(!_knownBlockVersions.checkAndUpdateVersion(clientId, blockId, version)) {
integrityViolationDetected("The block version number is too low. Did an attacker try to roll back the block or to re-introduce a deleted block?");
}
}
void IntegrityBlockStore2::_checkIdHeader(const Key &expectedKey, const Data &data) const {
Key actualKey = _readBlockId(data);
if (expectedKey != actualKey) {
integrityViolationDetected("The block key is wrong. Did an attacker try to rename some blocks?");
void IntegrityBlockStore2::_checkIdHeader(const BlockId &expectedBlockId, const Data &data) const {
BlockId actualBlockId = _readBlockId(data);
if (expectedBlockId != actualBlockId) {
integrityViolationDetected("The block id is wrong. Did an attacker try to rename some blocks?");
}
}
@ -71,8 +71,8 @@ uint32_t IntegrityBlockStore2::_readClientId(const Data &data) {
return clientId;
}
Key IntegrityBlockStore2::_readBlockId(const Data &data) {
return Key::FromBinary(data.dataOffset(ID_HEADER_OFFSET));
BlockId IntegrityBlockStore2::_readBlockId(const Data &data) {
return BlockId::FromBinary(data.dataOffset(ID_HEADER_OFFSET));
}
uint64_t IntegrityBlockStore2::_readVersion(const Data &data) {
@ -108,57 +108,57 @@ IntegrityBlockStore2::IntegrityBlockStore2(unique_ref<BlockStore2> baseBlockStor
: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath, myClientId), _noIntegrityChecks(noIntegrityChecks), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) {
}
bool IntegrityBlockStore2::tryCreate(const Key &key, const Data &data) {
bool IntegrityBlockStore2::tryCreate(const BlockId &blockId, const Data &data) {
_checkNoPastIntegrityViolations();
uint64_t version = _knownBlockVersions.incrementVersion(key);
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
return _baseBlockStore->tryCreate(key, dataWithHeader);
uint64_t version = _knownBlockVersions.incrementVersion(blockId);
Data dataWithHeader = _prependHeaderToData(blockId, _knownBlockVersions.myClientId(), version, data);
return _baseBlockStore->tryCreate(blockId, dataWithHeader);
}
bool IntegrityBlockStore2::remove(const Key &key) {
bool IntegrityBlockStore2::remove(const BlockId &blockId) {
_checkNoPastIntegrityViolations();
_knownBlockVersions.markBlockAsDeleted(key);
return _baseBlockStore->remove(key);
_knownBlockVersions.markBlockAsDeleted(blockId);
return _baseBlockStore->remove(blockId);
}
optional<Data> IntegrityBlockStore2::load(const Key &key) const {
optional<Data> IntegrityBlockStore2::load(const BlockId &blockId) const {
_checkNoPastIntegrityViolations();
auto loaded = _baseBlockStore->load(key);
auto loaded = _baseBlockStore->load(blockId);
if (none == loaded) {
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) {
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(blockId)) {
integrityViolationDetected("A block that should exist wasn't found. Did an attacker delete it?");
}
return optional<Data>(none);
}
#ifndef CRYFS_NO_COMPATIBILITY
if (FORMAT_VERSION_HEADER_OLD == _readFormatHeader(*loaded)) {
Data migrated = _migrateBlock(key, *loaded);
_checkHeader(key, migrated);
Data migrated = _migrateBlock(blockId, *loaded);
_checkHeader(blockId, migrated);
Data content = _removeHeader(migrated);
const_cast<IntegrityBlockStore2*>(this)->store(key, content);
const_cast<IntegrityBlockStore2*>(this)->store(blockId, content);
return optional<Data>(_removeHeader(migrated));
}
#endif
_checkHeader(key, *loaded);
_checkHeader(blockId, *loaded);
return optional<Data>(_removeHeader(*loaded));
}
#ifndef CRYFS_NO_COMPATIBILITY
Data IntegrityBlockStore2::_migrateBlock(const Key &key, const Data &data) {
Data migrated(data.size() + Key::BINARY_LENGTH);
Data IntegrityBlockStore2::_migrateBlock(const BlockId &blockId, const Data &data) {
Data migrated(data.size() + BlockId::BINARY_LENGTH);
std::memcpy(migrated.dataOffset(0), &FORMAT_VERSION_HEADER, sizeof(FORMAT_VERSION_HEADER));
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), key.data().data(), Key::BINARY_LENGTH);
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET + Key::BINARY_LENGTH), data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER));
ASSERT(migrated.size() == sizeof(FORMAT_VERSION_HEADER) + Key::BINARY_LENGTH + (data.size() - sizeof(FORMAT_VERSION_HEADER)), "Wrong offset computation");
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET), blockId.data().data(), BlockId::BINARY_LENGTH);
std::memcpy(migrated.dataOffset(ID_HEADER_OFFSET + BlockId::BINARY_LENGTH), data.dataOffset(sizeof(FORMAT_VERSION_HEADER)), data.size() - sizeof(FORMAT_VERSION_HEADER));
ASSERT(migrated.size() == sizeof(FORMAT_VERSION_HEADER) + BlockId::BINARY_LENGTH + (data.size() - sizeof(FORMAT_VERSION_HEADER)), "Wrong offset computation");
return migrated;
}
#endif
void IntegrityBlockStore2::store(const Key &key, const Data &data) {
void IntegrityBlockStore2::store(const BlockId &blockId, const Data &data) {
_checkNoPastIntegrityViolations();
uint64_t version = _knownBlockVersions.incrementVersion(key);
Data dataWithHeader = _prependHeaderToData(key, _knownBlockVersions.myClientId(), version, data);
return _baseBlockStore->store(key, dataWithHeader);
uint64_t version = _knownBlockVersions.incrementVersion(blockId);
Data dataWithHeader = _prependHeaderToData(blockId, _knownBlockVersions.myClientId(), version, data);
return _baseBlockStore->store(blockId, dataWithHeader);
}
uint64_t IntegrityBlockStore2::numBlocks() const {
@ -177,16 +177,16 @@ uint64_t IntegrityBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize
return baseBlockSize - HEADER_LENGTH;
}
void IntegrityBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
void IntegrityBlockStore2::forEachBlock(std::function<void (const BlockId &)> callback) const {
if (!_missingBlockIsIntegrityViolation) {
return _baseBlockStore->forEachBlock(std::move(callback));
}
std::unordered_set<blockstore::Key> existingBlocks = _knownBlockVersions.existingBlocks();
_baseBlockStore->forEachBlock([&existingBlocks, callback] (const Key &key) {
callback(key);
std::unordered_set<blockstore::BlockId> existingBlocks = _knownBlockVersions.existingBlocks();
_baseBlockStore->forEachBlock([&existingBlocks, callback] (const BlockId &blockId) {
callback(blockId);
auto found = existingBlocks.find(key);
auto found = existingBlocks.find(blockId);
if (found != existingBlocks.end()) {
existingBlocks.erase(found);
}
@ -200,23 +200,23 @@ void IntegrityBlockStore2::forEachBlock(std::function<void (const Key &)> callba
void IntegrityBlockStore2::migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId) {
std::cout << "Migrating file system for integrity features. Please don't interrupt this process. This can take a while..." << std::flush;
KnownBlockVersions knownBlockVersions(integrityFilePath, myClientId);
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions] (const Key &key) {
migrateBlockFromBlockstoreWithoutVersionNumbers(baseBlockStore, key, &knownBlockVersions);
baseBlockStore->forEachBlock([&baseBlockStore, &knownBlockVersions] (const BlockId &blockId) {
migrateBlockFromBlockstoreWithoutVersionNumbers(baseBlockStore, blockId, &knownBlockVersions);
});
std::cout << "done" << std::endl;
}
void IntegrityBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers(blockstore::BlockStore2* baseBlockStore, const blockstore::Key& key, KnownBlockVersions *knownBlockVersions) {
uint64_t version = knownBlockVersions->incrementVersion(key);
void IntegrityBlockStore2::migrateBlockFromBlockstoreWithoutVersionNumbers(blockstore::BlockStore2* baseBlockStore, const blockstore::BlockId& blockId, KnownBlockVersions *knownBlockVersions) {
uint64_t version = knownBlockVersions->incrementVersion(blockId);
auto data_ = baseBlockStore->load(key);
auto data_ = baseBlockStore->load(blockId);
if (data_ == boost::none) {
LOG(WARN, "Block not found, but was returned from forEachBlock before");
return;
}
cpputils::Data data = std::move(*data_);
cpputils::Data dataWithHeader = _prependHeaderToData(key, knownBlockVersions->myClientId(), version, std::move(data));
baseBlockStore->store(key, std::move(dataWithHeader));
cpputils::Data dataWithHeader = _prependHeaderToData(blockId, knownBlockVersions->myClientId(), version, std::move(data));
baseBlockStore->store(blockId, std::move(dataWithHeader));
}
#endif

View File

@ -18,14 +18,14 @@ class IntegrityBlockStore2 final: public BlockStore2 {
public:
IntegrityBlockStore2(cpputils::unique_ref<BlockStore2> baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
bool tryCreate(const Key &key, const cpputils::Data &data) override;
bool remove(const Key &key) override;
boost::optional<cpputils::Data> load(const Key &key) const override;
void store(const Key &key, const cpputils::Data &data) override;
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
// This format version is prepended to blocks to allow future versions to have compatibility.
@ -37,28 +37,28 @@ private:
public:
static constexpr uint64_t VERSION_ZERO = 0;
static constexpr unsigned int ID_HEADER_OFFSET = sizeof(FORMAT_VERSION_HEADER);
static constexpr unsigned int CLIENTID_HEADER_OFFSET = ID_HEADER_OFFSET + Key::BINARY_LENGTH;
static constexpr unsigned int CLIENTID_HEADER_OFFSET = ID_HEADER_OFFSET + BlockId::BINARY_LENGTH;
static constexpr unsigned int VERSION_HEADER_OFFSET = CLIENTID_HEADER_OFFSET + sizeof(uint32_t);
static constexpr unsigned int HEADER_LENGTH = VERSION_HEADER_OFFSET + sizeof(VERSION_ZERO);
#ifndef CRYFS_NO_COMPATIBILITY
static void migrateFromBlockstoreWithoutVersionNumbers(BlockStore2 *baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId);
static void migrateBlockFromBlockstoreWithoutVersionNumbers(BlockStore2* baseBlockStore, const blockstore::Key& key, KnownBlockVersions *knownBlockVersions);
static void migrateBlockFromBlockstoreWithoutVersionNumbers(BlockStore2* baseBlockStore, const blockstore::BlockId &blockId, KnownBlockVersions *knownBlockVersions);
#endif
private:
static cpputils::Data _prependHeaderToData(const Key& key, uint32_t myClientId, uint64_t version, const cpputils::Data &data);
void _checkHeader(const Key &key, const cpputils::Data &data) const;
static cpputils::Data _prependHeaderToData(const BlockId &blockId, uint32_t myClientId, uint64_t version, const cpputils::Data &data);
void _checkHeader(const BlockId &blockId, const cpputils::Data &data) const;
void _checkFormatHeader(const cpputils::Data &data) const;
void _checkIdHeader(const Key &expectedKey, const cpputils::Data &data) const;
void _checkVersionHeader(const Key &key, const cpputils::Data &data) const;
void _checkIdHeader(const BlockId &expectedBlockId, const cpputils::Data &data) const;
void _checkVersionHeader(const BlockId &blockId, const cpputils::Data &data) const;
static uint16_t _readFormatHeader(const cpputils::Data &data);
static uint32_t _readClientId(const cpputils::Data &data);
static Key _readBlockId(const cpputils::Data &data);
static BlockId _readBlockId(const cpputils::Data &data);
static uint64_t _readVersion(const cpputils::Data &data);
#ifndef CRYFS_NO_COMPATIBILITY
static cpputils::Data _migrateBlock(const Key &key, const cpputils::Data &data);
static cpputils::Data _migrateBlock(const BlockId &blockId, const cpputils::Data &data);
#endif
static cpputils::Data _removeHeader(const cpputils::Data &data);
void _checkNoPastIntegrityViolations() const;

View File

@ -47,22 +47,22 @@ KnownBlockVersions::~KnownBlockVersions() {
}
}
bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const Key &key, uint64_t version) {
bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const BlockId &blockId, uint64_t version) {
unique_lock<mutex> lock(_mutex);
ASSERT(clientId != CLIENT_ID_FOR_DELETED_BLOCK, "This is not a valid client id");
ASSERT(version > 0, "Version has to be >0"); // Otherwise we wouldn't handle notexisting entries correctly.
ASSERT(_valid, "Object not valid due to a std::move");
uint64_t &found = _knownVersions[{clientId, key}]; // If the entry doesn't exist, this creates it with value 0.
uint64_t &found = _knownVersions[{clientId, blockId}]; // If the entry doesn't exist, this creates it with value 0.
if (found > version) {
// This client already published a newer block version. Rollbacks are not allowed.
return false;
}
uint32_t &lastUpdateClientId = _lastUpdateClientId[key]; // If entry doesn't exist, this creates it with value 0. However, in this case, found == 0 (and version > 0), which means found != version.
uint32_t &lastUpdateClientId = _lastUpdateClientId[blockId]; // If entry doesn't exist, this creates it with value 0. However, in this case, found == 0 (and version > 0), which means found != version.
if (found == version && lastUpdateClientId != clientId) {
// This is a roll back to the "newest" block of client [clientId], which was since then superseded by a version from client _lastUpdateClientId[key].
// This is a roll back to the "newest" block of client [clientId], which was since then superseded by a version from client _lastUpdateClientId[blockId].
// This is not allowed.
return false;
}
@ -72,16 +72,16 @@ bool KnownBlockVersions::checkAndUpdateVersion(uint32_t clientId, const Key &key
return true;
}
uint64_t KnownBlockVersions::incrementVersion(const Key &key) {
uint64_t KnownBlockVersions::incrementVersion(const BlockId &blockId) {
unique_lock<mutex> lock(_mutex);
uint64_t &found = _knownVersions[{_myClientId, key}]; // If the entry doesn't exist, this creates it with value 0.
uint64_t &found = _knownVersions[{_myClientId, blockId}]; // If the entry doesn't exist, this creates it with value 0.
uint64_t newVersion = found + 1;
if (newVersion == std::numeric_limits<uint64_t>::max()) {
// It's *very* unlikely we ever run out of version numbers in 64bit...but just to be sure...
throw std::runtime_error("Version overflow");
}
found = newVersion;
_lastUpdateClientId[key] = _myClientId;
_lastUpdateClientId[blockId] = _myClientId;
return found;
}
@ -106,8 +106,8 @@ void KnownBlockVersions::_loadStateFile() {
void KnownBlockVersions::_saveStateFile() const {
Serializer serializer(
Serializer::StringSize(HEADER) +
sizeof(uint64_t) + _knownVersions.size() * (sizeof(uint32_t) + Key::BINARY_LENGTH + sizeof(uint64_t)) +
sizeof(uint64_t) + _lastUpdateClientId.size() * (Key::BINARY_LENGTH + sizeof(uint32_t)));
sizeof(uint64_t) + _knownVersions.size() * (sizeof(uint32_t) + BlockId::BINARY_LENGTH + sizeof(uint64_t)) +
sizeof(uint64_t) + _lastUpdateClientId.size() * (BlockId::BINARY_LENGTH + sizeof(uint32_t)));
serializer.writeString(HEADER);
_serializeKnownVersions(&serializer);
_serializeLastUpdateClientIds(&serializer);
@ -134,17 +134,17 @@ void KnownBlockVersions::_serializeKnownVersions(Serializer *serializer) const {
}
}
pair<ClientIdAndBlockKey, uint64_t> KnownBlockVersions::_deserializeKnownVersionsEntry(Deserializer *deserializer) {
pair<ClientIdAndBlockId, uint64_t> KnownBlockVersions::_deserializeKnownVersionsEntry(Deserializer *deserializer) {
uint32_t clientId = deserializer->readUint32();
Key blockKey(deserializer->readFixedSizeData<Key::BINARY_LENGTH>());
BlockId blockId(deserializer->readFixedSizeData<BlockId::BINARY_LENGTH>());
uint64_t version = deserializer->readUint64();
return {{clientId, blockKey}, version};
return {{clientId, blockId}, version};
};
void KnownBlockVersions::_serializeKnownVersionsEntry(Serializer *serializer, const pair<ClientIdAndBlockKey, uint64_t> &entry) {
void KnownBlockVersions::_serializeKnownVersionsEntry(Serializer *serializer, const pair<ClientIdAndBlockId, uint64_t> &entry) {
serializer->writeUint32(entry.first.clientId);
serializer->writeFixedSizeData<Key::BINARY_LENGTH>(entry.first.blockKey.data());
serializer->writeFixedSizeData<BlockId::BINARY_LENGTH>(entry.first.blockId.data());
serializer->writeUint64(entry.second);
}
@ -167,15 +167,15 @@ void KnownBlockVersions::_serializeLastUpdateClientIds(Serializer *serializer) c
}
}
pair<Key, uint32_t> KnownBlockVersions::_deserializeLastUpdateClientIdEntry(Deserializer *deserializer) {
Key blockKey(deserializer->readFixedSizeData<Key::BINARY_LENGTH>());
pair<BlockId, uint32_t> KnownBlockVersions::_deserializeLastUpdateClientIdEntry(Deserializer *deserializer) {
BlockId blockId(deserializer->readFixedSizeData<BlockId::BINARY_LENGTH>());
uint32_t clientId = deserializer->readUint32();
return {blockKey, clientId};
return {blockId, clientId};
};
void KnownBlockVersions::_serializeLastUpdateClientIdEntry(Serializer *serializer, const pair<Key, uint32_t> &entry) {
serializer->writeFixedSizeData<Key::BINARY_LENGTH>(entry.first.data());
void KnownBlockVersions::_serializeLastUpdateClientIdEntry(Serializer *serializer, const pair<BlockId, uint32_t> &entry) {
serializer->writeFixedSizeData<BlockId::BINARY_LENGTH>(entry.first.data());
serializer->writeUint32(entry.second);
}
@ -183,17 +183,17 @@ uint32_t KnownBlockVersions::myClientId() const {
return _myClientId;
}
uint64_t KnownBlockVersions::getBlockVersion(uint32_t clientId, const Key &key) const {
uint64_t KnownBlockVersions::getBlockVersion(uint32_t clientId, const BlockId &blockId) const {
unique_lock<mutex> lock(_mutex);
return _knownVersions.at({clientId, key});
return _knownVersions.at({clientId, blockId});
}
void KnownBlockVersions::markBlockAsDeleted(const Key &key) {
_lastUpdateClientId[key] = CLIENT_ID_FOR_DELETED_BLOCK;
void KnownBlockVersions::markBlockAsDeleted(const BlockId &blockId) {
_lastUpdateClientId[blockId] = CLIENT_ID_FOR_DELETED_BLOCK;
}
bool KnownBlockVersions::blockShouldExist(const Key &key) const {
auto found = _lastUpdateClientId.find(key);
bool KnownBlockVersions::blockShouldExist(const BlockId &blockId) const {
auto found = _lastUpdateClientId.find(blockId);
if (found == _lastUpdateClientId.end()) {
// We've never seen (i.e. loaded) this block. So we can't say it has to exist.
return false;
@ -202,8 +202,8 @@ bool KnownBlockVersions::blockShouldExist(const Key &key) const {
return found->second != CLIENT_ID_FOR_DELETED_BLOCK;
}
std::unordered_set<Key> KnownBlockVersions::existingBlocks() const {
std::unordered_set<Key> result;
std::unordered_set<BlockId> KnownBlockVersions::existingBlocks() const {
std::unordered_set<BlockId> result;
for (const auto &entry : _lastUpdateClientId) {
if (entry.second != CLIENT_ID_FOR_DELETED_BLOCK) {
result.insert(entry.first);

View File

@ -3,10 +3,10 @@
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_INTEGRITY_KNOWNBLOCKVERSIONS_H_
#include <cpp-utils/macros.h>
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include "ClientIdAndBlockKey.h"
#include "ClientIdAndBlockId.h"
#include <cpp-utils/data/Deserializer.h>
#include <cpp-utils/data/Serializer.h>
#include <mutex>
@ -22,16 +22,16 @@ namespace blockstore {
~KnownBlockVersions();
__attribute__((warn_unused_result))
bool checkAndUpdateVersion(uint32_t clientId, const Key &key, uint64_t version);
bool checkAndUpdateVersion(uint32_t clientId, const BlockId &blockId, uint64_t version);
uint64_t incrementVersion(const Key &key);
uint64_t incrementVersion(const BlockId &blockId);
void markBlockAsDeleted(const Key &key);
void markBlockAsDeleted(const BlockId &blockId);
bool blockShouldExist(const Key &key) const;
std::unordered_set<Key> existingBlocks() const;
bool blockShouldExist(const BlockId &blockId) const;
std::unordered_set<BlockId> existingBlocks() const;
uint64_t getBlockVersion(uint32_t clientId, const Key &key) const;
uint64_t getBlockVersion(uint32_t clientId, const BlockId &blockId) const;
uint32_t myClientId() const;
const boost::filesystem::path &path() const;
@ -39,8 +39,8 @@ namespace blockstore {
static constexpr uint32_t CLIENT_ID_FOR_DELETED_BLOCK = 0;
private:
std::unordered_map<ClientIdAndBlockKey, uint64_t> _knownVersions;
std::unordered_map<Key, uint32_t> _lastUpdateClientId; // The client who last updated the block
std::unordered_map<ClientIdAndBlockId, uint64_t> _knownVersions;
std::unordered_map<BlockId, uint32_t> _lastUpdateClientId; // The client who last updated the block
boost::filesystem::path _stateFilePath;
uint32_t _myClientId;
@ -55,14 +55,14 @@ namespace blockstore {
void _deserializeKnownVersions(cpputils::Deserializer *deserializer);
void _serializeKnownVersions(cpputils::Serializer *serializer) const;
static std::pair<ClientIdAndBlockKey, uint64_t> _deserializeKnownVersionsEntry(cpputils::Deserializer *deserializer);
static void _serializeKnownVersionsEntry(cpputils::Serializer *serializer, const std::pair<ClientIdAndBlockKey, uint64_t> &entry);
static std::pair<ClientIdAndBlockId, uint64_t> _deserializeKnownVersionsEntry(cpputils::Deserializer *deserializer);
static void _serializeKnownVersionsEntry(cpputils::Serializer *serializer, const std::pair<ClientIdAndBlockId, uint64_t> &entry);
void _deserializeLastUpdateClientIds(cpputils::Deserializer *deserializer);
void _serializeLastUpdateClientIds(cpputils::Serializer *serializer) const;
static std::pair<Key, uint32_t> _deserializeLastUpdateClientIdEntry(cpputils::Deserializer *deserializer);
static void _serializeLastUpdateClientIdEntry(cpputils::Serializer *serializer, const std::pair<Key, uint32_t> &entry);
static std::pair<BlockId, uint32_t> _deserializeLastUpdateClientIdEntry(cpputils::Deserializer *deserializer);
static void _serializeLastUpdateClientIdEntry(cpputils::Serializer *serializer, const std::pair<BlockId, uint32_t> &entry);
DISALLOW_COPY_AND_ASSIGN(KnownBlockVersions);
};

View File

@ -12,30 +12,30 @@ using std::mutex;
namespace blockstore {
namespace lowtohighlevel {
optional<unique_ref<LowToHighLevelBlock>> LowToHighLevelBlock::TryCreateNew(BlockStore2 *baseBlockStore, const Key &key, Data data) {
bool success = baseBlockStore->tryCreate(key, data);
optional<unique_ref<LowToHighLevelBlock>> LowToHighLevelBlock::TryCreateNew(BlockStore2 *baseBlockStore, const BlockId &blockId, Data data) {
bool success = baseBlockStore->tryCreate(blockId, data);
if (!success) {
return none;
}
return make_unique_ref<LowToHighLevelBlock>(key, std::move(data), baseBlockStore);
return make_unique_ref<LowToHighLevelBlock>(blockId, std::move(data), baseBlockStore);
}
unique_ref<LowToHighLevelBlock> LowToHighLevelBlock::Overwrite(BlockStore2 *baseBlockStore, const Key &key, Data data) {
baseBlockStore->store(key, data); // TODO Does it make sense to not store here, but only write back in the destructor of LowToHighLevelBlock? Also: What about tryCreate?
return make_unique_ref<LowToHighLevelBlock>(key, std::move(data), baseBlockStore);
unique_ref<LowToHighLevelBlock> LowToHighLevelBlock::Overwrite(BlockStore2 *baseBlockStore, const BlockId &blockId, Data data) {
baseBlockStore->store(blockId, data); // TODO Does it make sense to not store here, but only write back in the destructor of LowToHighLevelBlock? Also: What about tryCreate?
return make_unique_ref<LowToHighLevelBlock>(blockId, std::move(data), baseBlockStore);
}
optional<unique_ref<LowToHighLevelBlock>> LowToHighLevelBlock::Load(BlockStore2 *baseBlockStore, const Key &key) {
optional<Data> loadedData = baseBlockStore->load(key);
optional<unique_ref<LowToHighLevelBlock>> LowToHighLevelBlock::Load(BlockStore2 *baseBlockStore, const BlockId &blockId) {
optional<Data> loadedData = baseBlockStore->load(blockId);
if (loadedData == none) {
return none;
}
return make_unique_ref<LowToHighLevelBlock>(key, std::move(*loadedData), baseBlockStore);
return make_unique_ref<LowToHighLevelBlock>(blockId, std::move(*loadedData), baseBlockStore);
}
LowToHighLevelBlock::LowToHighLevelBlock(const Key& key, Data data, BlockStore2 *baseBlockStore)
:Block(key),
LowToHighLevelBlock::LowToHighLevelBlock(const BlockId &blockId, Data data, BlockStore2 *baseBlockStore)
:Block(blockId),
_baseBlockStore(baseBlockStore),
_data(std::move(data)),
_dataChanged(false),
@ -73,7 +73,7 @@ void LowToHighLevelBlock::resize(size_t newSize) {
void LowToHighLevelBlock::_storeToBaseBlock() {
if (_dataChanged) {
_baseBlockStore->store(key(), _data);
_baseBlockStore->store(blockId(), _data);
_dataChanged = false;
}
}

View File

@ -23,11 +23,11 @@ namespace lowtohighlevel {
class LowToHighLevelBlock final: public Block {
public:
static boost::optional<cpputils::unique_ref<LowToHighLevelBlock>> TryCreateNew(BlockStore2 *baseBlockStore, const Key &key, cpputils::Data data);
static cpputils::unique_ref<LowToHighLevelBlock> Overwrite(BlockStore2 *baseBlockStore, const Key &key, cpputils::Data data);
static boost::optional<cpputils::unique_ref<LowToHighLevelBlock>> Load(BlockStore2 *baseBlockStore, const Key &key);
static boost::optional<cpputils::unique_ref<LowToHighLevelBlock>> TryCreateNew(BlockStore2 *baseBlockStore, const BlockId &blockId, cpputils::Data data);
static cpputils::unique_ref<LowToHighLevelBlock> Overwrite(BlockStore2 *baseBlockStore, const BlockId &blockId, cpputils::Data data);
static boost::optional<cpputils::unique_ref<LowToHighLevelBlock>> Load(BlockStore2 *baseBlockStore, const BlockId &blockId);
LowToHighLevelBlock(const Key& key, cpputils::Data data, BlockStore2 *baseBlockStore);
LowToHighLevelBlock(const BlockId &blockId, cpputils::Data data, BlockStore2 *baseBlockStore);
~LowToHighLevelBlock();
const void *data() const override;

View File

@ -17,38 +17,38 @@ LowToHighLevelBlockStore::LowToHighLevelBlockStore(unique_ref<BlockStore2> baseB
: _baseBlockStore(std::move(baseBlockStore)) {
}
Key LowToHighLevelBlockStore::createKey() {
BlockId LowToHighLevelBlockStore::createBlockId() {
// TODO Is this the right way?
return Key::Random();
return BlockId::Random();
}
optional<unique_ref<Block>> LowToHighLevelBlockStore::tryCreate(const Key &key, Data data) {
optional<unique_ref<Block>> LowToHighLevelBlockStore::tryCreate(const BlockId &blockId, Data data) {
//TODO Easier implementation? This is only so complicated because of the cast LowToHighLevelBlock -> Block
auto result = LowToHighLevelBlock::TryCreateNew(_baseBlockStore.get(), key, std::move(data));
auto result = LowToHighLevelBlock::TryCreateNew(_baseBlockStore.get(), blockId, std::move(data));
if (result == none) {
return none;
}
return unique_ref<Block>(std::move(*result));
}
unique_ref<Block> LowToHighLevelBlockStore::overwrite(const Key &key, Data data) {
unique_ref<Block> LowToHighLevelBlockStore::overwrite(const BlockId &blockId, Data data) {
return unique_ref<Block>(
LowToHighLevelBlock::Overwrite(_baseBlockStore.get(), key, std::move(data))
LowToHighLevelBlock::Overwrite(_baseBlockStore.get(), blockId, std::move(data))
);
}
optional<unique_ref<Block>> LowToHighLevelBlockStore::load(const Key &key) {
auto result = optional<unique_ref<Block>>(LowToHighLevelBlock::Load(_baseBlockStore.get(), key));
optional<unique_ref<Block>> LowToHighLevelBlockStore::load(const BlockId &blockId) {
auto result = optional<unique_ref<Block>>(LowToHighLevelBlock::Load(_baseBlockStore.get(), blockId));
if (result == none) {
return none;
}
return unique_ref<Block>(std::move(*result));
}
void LowToHighLevelBlockStore::remove(const Key &key) {
bool success = _baseBlockStore->remove(key);
void LowToHighLevelBlockStore::remove(const BlockId &blockId) {
bool success = _baseBlockStore->remove(blockId);
if (!success) {
throw std::runtime_error("Couldn't delete block with id " + key.ToString());
throw std::runtime_error("Couldn't delete block with id " + blockId.ToString());
}
}
@ -64,7 +64,7 @@ uint64_t LowToHighLevelBlockStore::blockSizeFromPhysicalBlockSize(uint64_t block
return _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
}
void LowToHighLevelBlockStore::forEachBlock(std::function<void (const Key &)> callback) const {
void LowToHighLevelBlockStore::forEachBlock(std::function<void (const BlockId &)> callback) const {
_baseBlockStore->forEachBlock(std::move(callback));
}

View File

@ -20,15 +20,15 @@ class LowToHighLevelBlockStore final: public BlockStore {
public:
LowToHighLevelBlockStore(cpputils::unique_ref<BlockStore2> baseBlockStore);
Key createKey() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
cpputils::unique_ref<Block> overwrite(const blockstore::Key &key, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const Key &key) override;
void remove(const Key &key) override;
BlockId createBlockId() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) override;
cpputils::unique_ref<Block> overwrite(const blockstore::BlockId &blockId, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) override;
void remove(const BlockId &blockId) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
cpputils::unique_ref<BlockStore2> _baseBlockStore;

View File

@ -5,12 +5,12 @@ namespace blockstore {
namespace mock {
void MockBlock::write(const void *source, uint64_t offset, uint64_t size) {
_blockStore->_increaseNumWrittenBlocks(key());
_blockStore->_increaseNumWrittenBlocks(blockId());
return _baseBlock->write(source, offset, size);
}
void MockBlock::resize(size_t newSize) {
_blockStore->_increaseNumResizedBlocks(key());
_blockStore->_increaseNumResizedBlocks(blockId());
return _baseBlock->resize(newSize);
}

View File

@ -13,7 +13,7 @@ namespace blockstore {
class MockBlock final : public blockstore::Block {
public:
MockBlock(cpputils::unique_ref<blockstore::Block> baseBlock, MockBlockStore *blockStore)
:Block(baseBlock->key()), _baseBlock(std::move(baseBlock)), _blockStore(blockStore) {
:Block(baseBlock->blockId()), _baseBlock(std::move(baseBlock)), _blockStore(blockStore) {
}
const void *data() const override {

View File

@ -19,36 +19,36 @@ namespace blockstore {
: _mutex(), _baseBlockStore(std::move(baseBlockStore)), _loadedBlocks(), _createdBlocks(0), _writtenBlocks(), _resizedBlocks(), _removedBlocks() {
}
Key createKey() override {
return _baseBlockStore->createKey();
BlockId createBlockId() override {
return _baseBlockStore->createBlockId();
}
boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override {
boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) override {
_increaseNumCreatedBlocks();
auto base = _baseBlockStore->tryCreate(key, std::move(data));
auto base = _baseBlockStore->tryCreate(blockId, std::move(data));
if (base == boost::none) {
return boost::none;
}
return boost::optional<cpputils::unique_ref<Block>>(cpputils::make_unique_ref<MockBlock>(std::move(*base), this));
}
boost::optional<cpputils::unique_ref<Block>> load(const Key &key) override {
_increaseNumLoadedBlocks(key);
auto base = _baseBlockStore->load(key);
boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) override {
_increaseNumLoadedBlocks(blockId);
auto base = _baseBlockStore->load(blockId);
if (base == boost::none) {
return boost::none;
}
return boost::optional<cpputils::unique_ref<Block>>(cpputils::make_unique_ref<MockBlock>(std::move(*base), this));
}
cpputils::unique_ref<Block> overwrite(const Key &key, cpputils::Data data) override {
_increaseNumWrittenBlocks(key);
return _baseBlockStore->overwrite(key, std::move(data));
cpputils::unique_ref<Block> overwrite(const BlockId &blockId, cpputils::Data data) override {
_increaseNumWrittenBlocks(blockId);
return _baseBlockStore->overwrite(blockId, std::move(data));
}
void remove(const Key &key) override {
_increaseNumRemovedBlocks(key);
return _baseBlockStore->remove(key);
void remove(const BlockId &blockId) override {
_increaseNumRemovedBlocks(blockId);
return _baseBlockStore->remove(blockId);
}
uint64_t numBlocks() const override {
@ -63,12 +63,12 @@ namespace blockstore {
return _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
}
void forEachBlock(std::function<void(const Key &)> callback) const override {
void forEachBlock(std::function<void(const BlockId &)> callback) const override {
return _baseBlockStore->forEachBlock(callback);
}
void remove(cpputils::unique_ref<Block> block) override {
_increaseNumRemovedBlocks(block->key());
_increaseNumRemovedBlocks(block->blockId());
auto mockBlock = cpputils::dynamic_pointer_move<MockBlock>(block);
ASSERT(mockBlock != boost::none, "Wrong block type");
return _baseBlockStore->remove((*mockBlock)->releaseBaseBlock());
@ -86,25 +86,25 @@ namespace blockstore {
return _createdBlocks;
}
const std::vector<Key> &loadedBlocks() const {
const std::vector<BlockId> &loadedBlocks() const {
return _loadedBlocks;
}
const std::vector<Key> &removedBlocks() const {
const std::vector<BlockId> &removedBlocks() const {
return _removedBlocks;
}
const std::vector<Key> &resizedBlocks() const {
const std::vector<BlockId> &resizedBlocks() const {
return _resizedBlocks;
}
const std::vector<Key> &writtenBlocks() const {
const std::vector<BlockId> &writtenBlocks() const {
return _writtenBlocks;
}
std::vector<Key> distinctWrittenBlocks() const {
std::vector<Key> result(_writtenBlocks);
std::sort(result.begin(), result.end(), [](const Key &lhs, const Key &rhs) {
std::vector<BlockId> distinctWrittenBlocks() const {
std::vector<BlockId> result(_writtenBlocks);
std::sort(result.begin(), result.end(), [](const BlockId &lhs, const BlockId &rhs) {
return std::memcmp(lhs.data().data(), rhs.data().data(), lhs.BINARY_LENGTH) < 0;
});
result.erase(std::unique(result.begin(), result.end() ), result.end());
@ -117,24 +117,24 @@ namespace blockstore {
_createdBlocks += 1;
}
void _increaseNumLoadedBlocks(const Key &key) {
void _increaseNumLoadedBlocks(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_loadedBlocks.push_back(key);
_loadedBlocks.push_back(blockId);
}
void _increaseNumRemovedBlocks(const Key &key) {
void _increaseNumRemovedBlocks(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_removedBlocks.push_back(key);
_removedBlocks.push_back(blockId);
}
void _increaseNumResizedBlocks(const Key &key) {
void _increaseNumResizedBlocks(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_resizedBlocks.push_back(key);
_resizedBlocks.push_back(blockId);
}
void _increaseNumWrittenBlocks(const Key &key) {
void _increaseNumWrittenBlocks(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_writtenBlocks.push_back(key);
_writtenBlocks.push_back(blockId);
}
friend class MockBlock;
@ -142,11 +142,11 @@ namespace blockstore {
std::mutex _mutex;
cpputils::unique_ref<BlockStore> _baseBlockStore;
std::vector<Key> _loadedBlocks;
std::vector<BlockId> _loadedBlocks;
uint64_t _createdBlocks;
std::vector<Key> _writtenBlocks;
std::vector<Key> _resizedBlocks;
std::vector<Key> _removedBlocks;
std::vector<BlockId> _writtenBlocks;
std::vector<BlockId> _resizedBlocks;
std::vector<BlockId> _removedBlocks;
DISALLOW_COPY_AND_ASSIGN(MockBlockStore);
};

View File

@ -12,9 +12,9 @@ namespace ondisk {
const string OnDiskBlockStore2::FORMAT_VERSION_HEADER_PREFIX = "cryfs;block;";
const string OnDiskBlockStore2::FORMAT_VERSION_HEADER = OnDiskBlockStore2::FORMAT_VERSION_HEADER_PREFIX + "0";
boost::filesystem::path OnDiskBlockStore2::_getFilepath(const Key &key) const {
std::string keyStr = key.ToString();
return _rootDir / keyStr.substr(0,3) / keyStr.substr(3);
boost::filesystem::path OnDiskBlockStore2::_getFilepath(const BlockId &blockId) const {
std::string blockIdStr = blockId.ToString();
return _rootDir / blockIdStr.substr(0,3) / blockIdStr.substr(3);
}
Data OnDiskBlockStore2::_checkAndRemoveHeader(const Data &data) {
@ -45,24 +45,24 @@ unsigned int OnDiskBlockStore2::formatVersionHeaderSize() {
OnDiskBlockStore2::OnDiskBlockStore2(const boost::filesystem::path& path)
: _rootDir(path) {}
bool OnDiskBlockStore2::tryCreate(const Key &key, const Data &data) {
auto filepath = _getFilepath(key);
bool OnDiskBlockStore2::tryCreate(const BlockId &blockId, const Data &data) {
auto filepath = _getFilepath(blockId);
if (boost::filesystem::exists(filepath)) {
return false;
}
store(key, data);
store(blockId, data);
return true;
}
bool OnDiskBlockStore2::remove(const Key &key) {
auto filepath = _getFilepath(key);
bool OnDiskBlockStore2::remove(const BlockId &blockId) {
auto filepath = _getFilepath(blockId);
if (!boost::filesystem::is_regular_file(filepath)) { // TODO Is this branch necessary?
return false;
}
bool retval = boost::filesystem::remove(filepath);
if (!retval) {
cpputils::logging::LOG(cpputils::logging::ERROR, "Couldn't find block {} to remove", key.ToString());
cpputils::logging::LOG(cpputils::logging::ERROR, "Couldn't find block {} to remove", blockId.ToString());
return false;
}
if (boost::filesystem::is_empty(filepath.parent_path())) {
@ -71,19 +71,19 @@ bool OnDiskBlockStore2::remove(const Key &key) {
return true;
}
optional<Data> OnDiskBlockStore2::load(const Key &key) const {
auto fileContent = Data::LoadFromFile(_getFilepath(key));
optional<Data> OnDiskBlockStore2::load(const BlockId &blockId) const {
auto fileContent = Data::LoadFromFile(_getFilepath(blockId));
if (fileContent == none) {
return boost::none;
}
return _checkAndRemoveHeader(std::move(*fileContent));
}
void OnDiskBlockStore2::store(const Key &key, const Data &data) {
void OnDiskBlockStore2::store(const BlockId &blockId, const Data &data) {
Data fileContent(formatVersionHeaderSize() + data.size());
std::memcpy(fileContent.data(), FORMAT_VERSION_HEADER.c_str(), formatVersionHeaderSize());
std::memcpy(fileContent.dataOffset(formatVersionHeaderSize()), data.data(), data.size());
auto filepath = _getFilepath(key);
auto filepath = _getFilepath(blockId);
boost::filesystem::create_directory(filepath.parent_path()); // TODO Instead create all of them once at fs creation time?
fileContent.StoreToFile(filepath);
}
@ -114,13 +114,13 @@ uint64_t OnDiskBlockStore2::blockSizeFromPhysicalBlockSize(uint64_t blockSize) c
return blockSize - formatVersionHeaderSize();
}
void OnDiskBlockStore2::forEachBlock(std::function<void (const Key &)> callback) const {
void OnDiskBlockStore2::forEachBlock(std::function<void (const BlockId &)> callback) const {
for (auto prefixDir = boost::filesystem::directory_iterator(_rootDir); prefixDir != boost::filesystem::directory_iterator(); ++prefixDir) {
if (boost::filesystem::is_directory(prefixDir->path())) {
std::string blockKeyPrefix = prefixDir->path().filename().native();
std::string blockIdPrefix = prefixDir->path().filename().native();
for (auto block = boost::filesystem::directory_iterator(prefixDir->path()); block != boost::filesystem::directory_iterator(); ++block) {
std::string blockKeyPostfix = block->path().filename().native();
callback(Key::FromString(blockKeyPrefix + blockKeyPostfix));
std::string blockIdPostfix = block->path().filename().native();
callback(BlockId::FromString(blockIdPrefix + blockIdPostfix));
}
}
}

View File

@ -16,14 +16,14 @@ class OnDiskBlockStore2 final: public BlockStore2 {
public:
explicit OnDiskBlockStore2(const boost::filesystem::path& path);
bool tryCreate(const Key &key, const cpputils::Data &data) override;
bool remove(const Key &key) override;
boost::optional<cpputils::Data> load(const Key &key) const override;
void store(const Key &key, const cpputils::Data &data) override;
bool tryCreate(const BlockId &blockId, const cpputils::Data &data) override;
bool remove(const BlockId &blockId) override;
boost::optional<cpputils::Data> load(const BlockId &blockId) const override;
void store(const BlockId &blockId, const cpputils::Data &data) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
boost::filesystem::path _rootDir;
@ -31,7 +31,7 @@ private:
static const std::string FORMAT_VERSION_HEADER_PREFIX;
static const std::string FORMAT_VERSION_HEADER;
boost::filesystem::path _getFilepath(const Key &key) const;
boost::filesystem::path _getFilepath(const BlockId &blockId) const;
static cpputils::Data _checkAndRemoveHeader(const cpputils::Data &data);
static bool _isAcceptedCryfsHeader(const cpputils::Data &data);
static bool _isOtherCryfsHeader(const cpputils::Data &data);

View File

@ -11,10 +11,10 @@ namespace blockstore {
namespace parallelaccess {
class ParallelAccessBlockStore;
class BlockRef final: public Block, public parallelaccessstore::ParallelAccessStore<Block, BlockRef, Key>::ResourceRefBase {
class BlockRef final: public Block, public parallelaccessstore::ParallelAccessStore<Block, BlockRef, BlockId>::ResourceRefBase {
public:
//TODO Unneccessarily storing Key twice here (in parent class and in _baseBlock).
explicit BlockRef(Block *baseBlock): Block(baseBlock->key()), _baseBlock(baseBlock) {}
//TODO Unneccessarily storing BlockId twice here (in parent class and in _baseBlock).
explicit BlockRef(Block *baseBlock): Block(baseBlock->blockId()), _baseBlock(baseBlock) {}
const void *data() const override {
return _baseBlock->data();

View File

@ -23,50 +23,50 @@ ParallelAccessBlockStore::ParallelAccessBlockStore(unique_ref<BlockStore> baseBl
: _baseBlockStore(std::move(baseBlockStore)), _parallelAccessStore(make_unique_ref<ParallelAccessBlockStoreAdapter>(_baseBlockStore.get())) {
}
Key ParallelAccessBlockStore::createKey() {
return _baseBlockStore->createKey();
BlockId ParallelAccessBlockStore::createBlockId() {
return _baseBlockStore->createBlockId();
}
optional<unique_ref<Block>> ParallelAccessBlockStore::tryCreate(const Key &key, Data data) {
ASSERT(!_parallelAccessStore.isOpened(key), ("Key "+key.ToString()+"already exists").c_str());
auto block = _baseBlockStore->tryCreate(key, std::move(data));
optional<unique_ref<Block>> ParallelAccessBlockStore::tryCreate(const BlockId &blockId, Data data) {
ASSERT(!_parallelAccessStore.isOpened(blockId), ("BlockId "+blockId.ToString()+"already exists").c_str());
auto block = _baseBlockStore->tryCreate(blockId, std::move(data));
if (block == none) {
//TODO Test this code branch
return none;
}
return unique_ref<Block>(_parallelAccessStore.add(key, std::move(*block)));
return unique_ref<Block>(_parallelAccessStore.add(blockId, std::move(*block)));
}
optional<unique_ref<Block>> ParallelAccessBlockStore::load(const Key &key) {
auto block = _parallelAccessStore.load(key);
optional<unique_ref<Block>> ParallelAccessBlockStore::load(const BlockId &blockId) {
auto block = _parallelAccessStore.load(blockId);
if (block == none) {
return none;
}
return unique_ref<Block>(std::move(*block));
}
unique_ref<Block> ParallelAccessBlockStore::overwrite(const Key &key, Data data) {
unique_ref<Block> ParallelAccessBlockStore::overwrite(const BlockId &blockId, Data data) {
auto onExists = [&data] (BlockRef *block) {
if (block->size() != data.size()) {
block->resize(data.size());
}
block->write(data.data(), 0, data.size());
};
auto onAdd = [this, key, &data] {
return _baseBlockStore->overwrite(key, data.copy()); // TODO Without copy?
auto onAdd = [this, blockId, &data] {
return _baseBlockStore->overwrite(blockId, data.copy()); // TODO Without copy?
};
return _parallelAccessStore.loadOrAdd(key, onExists, onAdd);
return _parallelAccessStore.loadOrAdd(blockId, onExists, onAdd);
}
void ParallelAccessBlockStore::remove(unique_ref<Block> block) {
Key key = block->key();
BlockId blockId = block->blockId();
auto block_ref = dynamic_pointer_move<BlockRef>(block);
ASSERT(block_ref != none, "Block is not a BlockRef");
return _parallelAccessStore.remove(key, std::move(*block_ref));
return _parallelAccessStore.remove(blockId, std::move(*block_ref));
}
void ParallelAccessBlockStore::remove(const Key &key) {
return _parallelAccessStore.remove(key);
void ParallelAccessBlockStore::remove(const BlockId &blockId) {
return _parallelAccessStore.remove(blockId);
}
uint64_t ParallelAccessBlockStore::numBlocks() const {
@ -81,7 +81,7 @@ uint64_t ParallelAccessBlockStore::blockSizeFromPhysicalBlockSize(uint64_t block
return _baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize);
}
void ParallelAccessBlockStore::forEachBlock(std::function<void (const Key &)> callback) const {
void ParallelAccessBlockStore::forEachBlock(std::function<void (const BlockId &)> callback) const {
return _baseBlockStore->forEachBlock(callback);
}

View File

@ -15,20 +15,20 @@ class ParallelAccessBlockStore final: public BlockStore {
public:
explicit ParallelAccessBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore);
Key createKey() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const Key &key) override;
cpputils::unique_ref<Block> overwrite(const Key &key, cpputils::Data data) override;
void remove(const Key &key) override;
BlockId createBlockId() override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) override;
cpputils::unique_ref<Block> overwrite(const BlockId &blockId, cpputils::Data data) override;
void remove(const BlockId &blockId) override;
void remove(cpputils::unique_ref<Block> node) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
private:
cpputils::unique_ref<BlockStore> _baseBlockStore;
parallelaccessstore::ParallelAccessStore<Block, BlockRef, Key> _parallelAccessStore;
parallelaccessstore::ParallelAccessStore<Block, BlockRef, BlockId> _parallelAccessStore;
DISALLOW_COPY_AND_ASSIGN(ParallelAccessBlockStore);
};

View File

@ -9,22 +9,22 @@
namespace blockstore {
namespace parallelaccess {
class ParallelAccessBlockStoreAdapter final: public parallelaccessstore::ParallelAccessBaseStore<Block, Key> {
class ParallelAccessBlockStoreAdapter final: public parallelaccessstore::ParallelAccessBaseStore<Block, BlockId> {
public:
explicit ParallelAccessBlockStoreAdapter(BlockStore *baseBlockStore)
:_baseBlockStore(std::move(baseBlockStore)) {
}
boost::optional<cpputils::unique_ref<Block>> loadFromBaseStore(const Key &key) override {
return _baseBlockStore->load(key);
boost::optional<cpputils::unique_ref<Block>> loadFromBaseStore(const BlockId &blockId) override {
return _baseBlockStore->load(blockId);
}
void removeFromBaseStore(cpputils::unique_ref<Block> block) override {
return _baseBlockStore->remove(std::move(block));
}
void removeFromBaseStore(const Key &key) override {
return _baseBlockStore->remove(key);
void removeFromBaseStore(const BlockId &blockId) override {
return _baseBlockStore->remove(blockId);
}
private:

View File

@ -16,8 +16,8 @@ using cpputils::Data;
namespace blockstore {
namespace testfake {
FakeBlock::FakeBlock(FakeBlockStore *store, const Key &key, shared_ptr<Data> data, bool dirty)
: Block(key), _store(store), _data(data), _dataChanged(dirty) {
FakeBlock::FakeBlock(FakeBlockStore *store, const BlockId &blockId, shared_ptr<Data> data, bool dirty)
: Block(blockId), _store(store), _data(data), _dataChanged(dirty) {
}
FakeBlock::~FakeBlock() {
@ -45,7 +45,7 @@ void FakeBlock::resize(size_t newSize) {
void FakeBlock::flush() {
if(_dataChanged) {
_store->updateData(key(), *_data);
_store->updateData(blockId(), *_data);
_dataChanged = false;
}
}

View File

@ -13,7 +13,7 @@ class FakeBlockStore;
class FakeBlock final: public Block {
public:
FakeBlock(FakeBlockStore *store, const Key &key, std::shared_ptr<cpputils::Data> data, bool dirty);
FakeBlock(FakeBlockStore *store, const BlockId &blockId, std::shared_ptr<cpputils::Data> data, bool dirty);
~FakeBlock();
const void *data() const override;

View File

@ -19,21 +19,21 @@ namespace testfake {
FakeBlockStore::FakeBlockStore()
: _blocks(), _used_dataregions_for_blocks(), _mutex() {}
optional<unique_ref<Block>> FakeBlockStore::tryCreate(const Key &key, Data data) {
optional<unique_ref<Block>> FakeBlockStore::tryCreate(const BlockId &blockId, Data data) {
std::unique_lock<std::mutex> lock(_mutex);
auto insert_result = _blocks.emplace(key, std::move(data));
auto insert_result = _blocks.emplace(blockId, std::move(data));
if (!insert_result.second) {
return none;
}
//Return a copy of the stored data
return _load(key);
return _load(blockId);
}
unique_ref<Block> FakeBlockStore::overwrite(const Key &key, Data data) {
unique_ref<Block> FakeBlockStore::overwrite(const BlockId &blockId, Data data) {
std::unique_lock<std::mutex> lock(_mutex);
auto insert_result = _blocks.emplace(key, data.copy());
auto insert_result = _blocks.emplace(blockId, data.copy());
if (!insert_result.second) {
// If block already exists, overwrite it.
@ -41,42 +41,42 @@ unique_ref<Block> FakeBlockStore::overwrite(const Key &key, Data data) {
}
//Return a pointer to the stored FakeBlock
auto loaded = _load(key);
auto loaded = _load(blockId);
ASSERT(loaded != none, "Block was just created or written. Should exist.");
return std::move(*loaded);
}
optional<unique_ref<Block>> FakeBlockStore::load(const Key &key) {
optional<unique_ref<Block>> FakeBlockStore::load(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
return _load(key);
return _load(blockId);
}
optional<unique_ref<Block>> FakeBlockStore::_load(const Key &key) {
optional<unique_ref<Block>> FakeBlockStore::_load(const BlockId &blockId) {
//Return a copy of the stored data
try {
return makeFakeBlockFromData(key, _blocks.at(key), false);
return makeFakeBlockFromData(blockId, _blocks.at(blockId), false);
} catch (const std::out_of_range &e) {
return none;
}
}
void FakeBlockStore::remove(const Key &key) {
void FakeBlockStore::remove(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
int numRemoved = _blocks.erase(key);
int numRemoved = _blocks.erase(blockId);
ASSERT(numRemoved == 1, "Block not found");
}
unique_ref<Block> FakeBlockStore::makeFakeBlockFromData(const Key &key, const Data &data, bool dirty) {
unique_ref<Block> FakeBlockStore::makeFakeBlockFromData(const BlockId &blockId, const Data &data, bool dirty) {
auto newdata = make_shared<Data>(data.copy());
_used_dataregions_for_blocks.push_back(newdata);
return make_unique_ref<FakeBlock>(this, key, newdata, dirty);
return make_unique_ref<FakeBlock>(this, blockId, newdata, dirty);
}
void FakeBlockStore::updateData(const Key &key, const Data &data) {
void FakeBlockStore::updateData(const BlockId &blockId, const Data &data) {
std::unique_lock<std::mutex> lock(_mutex);
auto found = _blocks.find(key);
auto found = _blocks.find(blockId);
if (found == _blocks.end()) {
auto insertResult = _blocks.emplace(key, data.copy());
auto insertResult = _blocks.emplace(blockId, data.copy());
ASSERT(true == insertResult.second, "Inserting didn't work");
found = insertResult.first;
}
@ -97,7 +97,7 @@ uint64_t FakeBlockStore::blockSizeFromPhysicalBlockSize(uint64_t blockSize) cons
return blockSize;
}
void FakeBlockStore::forEachBlock(std::function<void (const Key &)> callback) const {
void FakeBlockStore::forEachBlock(std::function<void (const BlockId &)> callback) const {
for (const auto &entry : _blocks) {
callback(entry.first);
}

View File

@ -31,19 +31,19 @@ class FakeBlockStore final: public BlockStoreWithRandomKeys {
public:
FakeBlockStore();
boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) override;
cpputils::unique_ref<Block> overwrite(const blockstore::Key &key, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const Key &key) override;
void remove(const Key &key) override;
boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) override;
cpputils::unique_ref<Block> overwrite(const blockstore::BlockId &blockId, cpputils::Data data) override;
boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) override;
void remove(const BlockId &blockId) override;
uint64_t numBlocks() const override;
uint64_t estimateNumFreeBytes() const override;
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void forEachBlock(std::function<void (const BlockId &)> callback) const override;
void updateData(const Key &key, const cpputils::Data &data);
void updateData(const BlockId &blockId, const cpputils::Data &data);
private:
std::unordered_map<Key, cpputils::Data> _blocks;
std::unordered_map<BlockId, cpputils::Data> _blocks;
//This vector keeps a handle of the data regions for all created FakeBlock objects.
//This way, it is ensured that no two created FakeBlock objects will work on the
@ -54,8 +54,8 @@ private:
mutable std::mutex _mutex;
cpputils::unique_ref<Block> makeFakeBlockFromData(const Key &key, const cpputils::Data &data, bool dirty);
boost::optional<cpputils::unique_ref<Block>> _load(const Key &key);
cpputils::unique_ref<Block> makeFakeBlockFromData(const BlockId &blockId, const cpputils::Data &data, bool dirty);
boost::optional<cpputils::unique_ref<Block>> _load(const BlockId &blockId);
DISALLOW_COPY_AND_ASSIGN(FakeBlockStore);
};

View File

@ -2,7 +2,7 @@
#ifndef MESSMER_BLOCKSTORE_INTERFACE_BLOCK_H_
#define MESSMER_BLOCKSTORE_INTERFACE_BLOCK_H_
#include "../utils/Key.h"
#include "blockstore/utils/BlockId.h"
#include <cstring>
namespace blockstore {
@ -24,15 +24,15 @@ public:
//TODO Test resize()
virtual void resize(size_t newSize) = 0;
const Key &key() const {
return _key;
const BlockId &blockId() const {
return _blockId;
}
protected:
Block(const Key &key) : _key(key) {}
Block(const BlockId &blockId) : _blockId(blockId) {}
private:
const Key _key;
const BlockId _blockId;
};
}

View File

@ -14,15 +14,15 @@ class BlockStore {
public:
virtual ~BlockStore() {}
virtual Key createKey() = 0;
//Returns boost::none if key already exists
virtual BlockId createBlockId() = 0;
//Returns boost::none if id already exists
// TODO Can we make data passed in by ref?
virtual boost::optional<cpputils::unique_ref<Block>> tryCreate(const Key &key, cpputils::Data data) = 0;
//TODO Use boost::optional (if key doesn't exist)
// Return nullptr if block with this key doesn't exists
virtual boost::optional<cpputils::unique_ref<Block>> load(const Key &key) = 0;
virtual cpputils::unique_ref<Block> overwrite(const blockstore::Key &key, cpputils::Data data) = 0;
virtual void remove(const Key &key) = 0;
virtual boost::optional<cpputils::unique_ref<Block>> tryCreate(const BlockId &blockId, cpputils::Data data) = 0;
//TODO Use boost::optional (if id doesn't exist)
// Return nullptr if block with this id doesn't exists
virtual boost::optional<cpputils::unique_ref<Block>> load(const BlockId &blockId) = 0;
virtual cpputils::unique_ref<Block> overwrite(const blockstore::BlockId &blockId, cpputils::Data data) = 0;
virtual void remove(const BlockId &blockId) = 0;
virtual uint64_t numBlocks() const = 0;
//TODO Test estimateNumFreeBytes in all block stores
virtual uint64_t estimateNumFreeBytes() const = 0;
@ -31,18 +31,18 @@ public:
// This can be used to create blocks with a certain physical block size.
virtual uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const = 0; // TODO Test
virtual void forEachBlock(std::function<void (const Key &)> callback) const = 0;
virtual void forEachBlock(std::function<void (const BlockId &)> callback) const = 0;
virtual void remove(cpputils::unique_ref<Block> block) {
Key key = block->key();
BlockId blockId = block->blockId();
cpputils::destruct(std::move(block));
remove(key);
remove(blockId);
}
cpputils::unique_ref<Block> create(const cpputils::Data &data) {
while(true) {
//TODO Copy (data.copy()) necessary?
auto block = tryCreate(createKey(), data.copy());
auto block = tryCreate(createBlockId(), data.copy());
if (block != boost::none) {
return std::move(*block);
}

View File

@ -16,21 +16,21 @@ public:
virtual ~BlockStore2() {}
__attribute__((warn_unused_result))
virtual bool tryCreate(const Key &key, const cpputils::Data &data) = 0;
virtual bool tryCreate(const BlockId &blockId, const cpputils::Data &data) = 0;
__attribute__((warn_unused_result))
virtual bool remove(const Key &key) = 0;
virtual bool remove(const BlockId &blockId) = 0;
__attribute__((warn_unused_result))
virtual boost::optional<cpputils::Data> load(const Key &key) const = 0;
virtual boost::optional<cpputils::Data> load(const BlockId &blockId) const = 0;
// Store the block with the given key. If it doesn't exist, it is created.
virtual void store(const Key &key, const cpputils::Data &data) = 0;
// Store the block with the given blockId. If it doesn't exist, it is created.
virtual void store(const BlockId &blockId, const cpputils::Data &data) = 0;
Key create(const cpputils::Data& data) {
Key key = Key::Random();
bool success = tryCreate(key, data);
BlockId create(const cpputils::Data& data) {
BlockId blockId = BlockId::Random();
bool success = tryCreate(blockId, data);
if (success) {
return key;
return blockId;
} else {
return create(data);
}
@ -40,7 +40,7 @@ public:
//TODO Test estimateNumFreeBytes
virtual uint64_t estimateNumFreeBytes() const = 0;
virtual uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const = 0; // TODO Test
virtual void forEachBlock(std::function<void (const Key &)> callback) const = 0;
virtual void forEachBlock(std::function<void (const BlockId &)> callback) const = 0;
};
}

View File

@ -8,14 +8,14 @@
namespace blockstore {
// This is an implementation helpers for BlockStores that use random block keys.
// This is an implementation helpers for BlockStores that use random block ids.
// You should never give this static type to the client. The client should always
// work with the BlockStore interface instead.
// TODO Delete this class
class BlockStoreWithRandomKeys: public BlockStore {
public:
Key createKey() final {
return Key::Random();
BlockId createBlockId() final {
return BlockId::Random();
}
};

View File

@ -1 +1 @@
#include "Key.h"
#include "BlockId.h"

View File

@ -1,14 +1,13 @@
#pragma once
#ifndef MESSMER_BLOCKSTORE_UTILS_KEY_H_
#define MESSMER_BLOCKSTORE_UTILS_KEY_H_
#ifndef MESSMER_BLOCKSTORE_UTILS_BLOCKID_H_
#define MESSMER_BLOCKSTORE_UTILS_BLOCKID_H_
#include "IdWrapper.h"
namespace blockstore {
struct _BlockIdTag final {};
// A key here is NOT a key for encryption, but a key as used in key->value mappings ("access handle for a block").
// TODO Rename to BlockId and split from a BlobId (i.e. IdWrapper<BlobIdTag>)
// TODO Split from a BlobId (i.e. IdWrapper<BlobIdTag>)
using BlockId = IdWrapper<_BlockIdTag>;
}

View File

@ -27,7 +27,7 @@ namespace cryfs {
config.SetVersion(gitversion::VersionString());
config.SetCreatedWithVersion(gitversion::VersionString());
config.SetBlocksizeBytes(_generateBlocksizeBytes(blocksizeBytesFromCommandLine));
config.SetRootBlob(_generateRootBlobKey());
config.SetRootBlob(_generateRootBlobId());
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
config.SetFilesystemId(_generateFilesystemID());
uint32_t myClientId = MyClientId(LocalStateDir::forFilesystemId(config.FilesystemId())).loadOrGenerate();
@ -78,7 +78,7 @@ namespace cryfs {
return key;
}
string CryConfigCreator::_generateRootBlobKey() {
string CryConfigCreator::_generateRootBlobId() {
//An empty root blob entry will tell CryDevice to create a new root blob
return "";
}

View File

@ -23,7 +23,7 @@ namespace cryfs {
private:
std::string _generateCipher(const boost::optional<std::string> &cipherFromCommandLine);
std::string _generateEncKey(const std::string &cipher);
std::string _generateRootBlobKey();
std::string _generateRootBlobId();
uint32_t _generateBlocksizeBytes(const boost::optional<uint32_t> &blocksizeBytesFromCommandLine);
CryConfig::FilesystemID _generateFilesystemID();
boost::optional<uint32_t> _generateExclusiveClientId(const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine, uint32_t myClientId);

View File

@ -30,7 +30,7 @@ using fspp::fuse::FuseErrnoException;
using blockstore::BlockStore;
using blockstore::BlockStore2;
using blockstore::Key;
using blockstore::BlockId;
using blockstore::encrypted::EncryptedBlockStore2;
using blobstore::BlobStore;
using blockstore::lowtohighlevel::LowToHighLevelBlockStore;
@ -59,7 +59,7 @@ namespace cryfs {
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore2> blockStore, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation)
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation)),
_rootKey(GetOrCreateRootKey(&configFile)),
_rootBlobId(GetOrCreateRootBlobId(&configFile)),
_onFsAction() {
}
@ -81,11 +81,11 @@ unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CryDevice::Crea
#ifndef CRYFS_NO_COMPATIBILITY
unique_ref<fsblobstore::FsBlobStore> CryDevice::MigrateOrCreateFsBlobStore(unique_ref<BlobStore> blobStore, CryConfigFile *configFile) {
string rootBlobKey = configFile->config()->RootBlob();
if ("" == rootBlobKey) {
string rootBlobId = configFile->config()->RootBlob();
if ("" == rootBlobId) {
return make_unique_ref<FsBlobStore>(std::move(blobStore));
}
return FsBlobStore::migrateIfNeeded(std::move(blobStore), Key::FromString(rootBlobKey));
return FsBlobStore::migrateIfNeeded(std::move(blobStore), BlockId::FromString(rootBlobId));
}
#endif
@ -119,10 +119,10 @@ unique_ref<BlockStore2> CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref
return make_unique_ref<IntegrityBlockStore2>(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, missingBlockIsIntegrityViolation);
}
Key CryDevice::CreateRootBlobAndReturnKey() {
auto rootBlob = _fsBlobStore->createDirBlob(blockstore::Key::Null());
BlockId CryDevice::CreateRootBlobAndReturnId() {
auto rootBlob = _fsBlobStore->createDirBlob(blockstore::BlockId::Null());
rootBlob->flush(); // Don't cache, but directly write the root blob (this causes it to fail early if the base directory is not accessible)
return rootBlob->key();
return rootBlob->blockId();
}
optional<unique_ref<fspp::File>> CryDevice::LoadFile(const bf::path &path) {
@ -170,7 +170,7 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
if (path.parent_path().empty()) {
//We are asked to load the base directory '/'.
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, none, _rootKey));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, none, _rootBlobId));
}
auto parentWithGrandparent = LoadDirBlobWithParent(path.parent_path());
@ -185,11 +185,11 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
switch(entry.type()) {
case fspp::Dir::EntryType::DIR:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), std::move(grandparent), entry.key()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), std::move(grandparent), entry.blockId()));
case fspp::Dir::EntryType::FILE:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), std::move(grandparent), entry.key()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), std::move(grandparent), entry.blockId()));
case fspp::Dir::EntryType::SYMLINK:
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), std::move(grandparent), entry.key()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), std::move(grandparent), entry.blockId()));
}
ASSERT(false, "Switch/case not exhaustive");
}
@ -205,13 +205,13 @@ CryDevice::DirBlobWithParent CryDevice::LoadDirBlobWithParent(const bf::path &pa
CryDevice::BlobWithParent CryDevice::LoadBlobWithParent(const bf::path &path) {
optional<unique_ref<DirBlobRef>> parentBlob = none;
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootKey);
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootBlobId);
if (currentBlobOpt == none) {
LOG(ERROR, "Could not load root blob. Is the base directory accessible?");
throw FuseErrnoException(EIO);
}
unique_ref<FsBlobRef> currentBlob = std::move(*currentBlobOpt);
ASSERT(currentBlob->parentPointer() == Key::Null(), "Root Blob should have a nullptr as parent");
ASSERT(currentBlob->parentPointer() == BlockId::Null(), "Root Blob should have a nullptr as parent");
for (const bf::path &component : path.relative_path()) {
auto currentDir = dynamic_pointer_move<DirBlobRef>(currentBlob);
@ -223,14 +223,14 @@ CryDevice::BlobWithParent CryDevice::LoadBlobWithParent(const bf::path &path) {
if (childOpt == boost::none) {
throw FuseErrnoException(ENOENT); // Child entry in directory not found
}
Key childKey = childOpt->key();
auto nextBlob = _fsBlobStore->load(childKey);
BlockId childId = childOpt->blockId();
auto nextBlob = _fsBlobStore->load(childId);
if (nextBlob == none) {
throw FuseErrnoException(ENOENT); // Blob for directory entry not found
}
parentBlob = std::move(*currentDir);
currentBlob = std::move(*nextBlob);
ASSERT(currentBlob->parentPointer() == (*parentBlob)->key(), "Blob has wrong parent pointer");
ASSERT(currentBlob->parentPointer() == (*parentBlob)->blockId(), "Blob has wrong parent pointer");
}
return BlobWithParent{std::move(currentBlob), std::move(parentBlob)};
@ -258,46 +258,46 @@ void CryDevice::statfs(const bf::path &path, struct statvfs *fsstat) {
fsstat->f_frsize = fsstat->f_bsize; // even though this is supposed to be ignored, osxfuse needs it.
}
unique_ref<FileBlobRef> CryDevice::CreateFileBlob(const blockstore::Key &parent) {
unique_ref<FileBlobRef> CryDevice::CreateFileBlob(const blockstore::BlockId &parent) {
return _fsBlobStore->createFileBlob(parent);
}
unique_ref<DirBlobRef> CryDevice::CreateDirBlob(const blockstore::Key &parent) {
unique_ref<DirBlobRef> CryDevice::CreateDirBlob(const blockstore::BlockId &parent) {
return _fsBlobStore->createDirBlob(parent);
}
unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target, const blockstore::Key &parent) {
unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target, const blockstore::BlockId &parent) {
return _fsBlobStore->createSymlinkBlob(target, parent);
}
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
auto blob = _fsBlobStore->load(key);
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::BlockId &blockId) {
auto blob = _fsBlobStore->load(blockId);
if (blob == none) {
LOG(ERROR, "Could not load blob {}. Is the base directory accessible?", key.ToString());
LOG(ERROR, "Could not load blob {}. Is the base directory accessible?", blockId.ToString());
throw FuseErrnoException(EIO);
}
return std::move(*blob);
}
void CryDevice::RemoveBlob(const blockstore::Key &key) {
auto blob = _fsBlobStore->load(key);
void CryDevice::RemoveBlob(const blockstore::BlockId &blockId) {
auto blob = _fsBlobStore->load(blockId);
if (blob == none) {
LOG(ERROR, "Could not load blob. Is the base directory accessible?", key.ToString());
LOG(ERROR, "Could not load blob {}. Is the base directory accessible?", blockId.ToString());
throw FuseErrnoException(EIO);
}
_fsBlobStore->remove(std::move(*blob));
}
Key CryDevice::GetOrCreateRootKey(CryConfigFile *configFile) {
string root_key = configFile->config()->RootBlob();
if (root_key == "") {
auto new_key = CreateRootBlobAndReturnKey();
configFile->config()->SetRootBlob(new_key.ToString());
BlockId CryDevice::GetOrCreateRootBlobId(CryConfigFile *configFile) {
string root_blockId = configFile->config()->RootBlob();
if (root_blockId == "") {
auto new_blockId = CreateRootBlobAndReturnId();
configFile->config()->SetRootBlob(new_blockId.ToString());
configFile->save();
return new_key;
return new_blockId;
}
return Key::FromString(root_key);
return BlockId::FromString(root_blockId);
}
cpputils::unique_ref<blockstore::BlockStore2> CryDevice::CreateEncryptedBlockStore(const CryConfig &config, unique_ref<BlockStore2> baseBlockStore) {

View File

@ -22,16 +22,16 @@ public:
void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override;
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> CreateFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> CreateDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::SymlinkBlobRef> CreateSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob(const blockstore::Key &key);
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> CreateFileBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> CreateDirBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<parallelaccessfsblobstore::SymlinkBlobRef> CreateSymlinkBlob(const boost::filesystem::path &target, const blockstore::BlockId &parent);
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob(const blockstore::BlockId &blockId);
struct DirBlobWithParent {
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> blob;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent;
};
DirBlobWithParent LoadDirBlobWithParent(const boost::filesystem::path &path);
void RemoveBlob(const blockstore::Key &key);
void RemoveBlob(const blockstore::BlockId &blockId);
void onFsAction(std::function<void()> callback);
@ -48,11 +48,11 @@ private:
cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> _fsBlobStore;
blockstore::Key _rootKey;
blockstore::BlockId _rootBlobId;
std::vector<std::function<void()>> _onFsAction;
blockstore::Key GetOrCreateRootKey(CryConfigFile *config);
blockstore::Key CreateRootBlobAndReturnKey();
blockstore::BlockId GetOrCreateRootBlobId(CryConfigFile *config);
blockstore::BlockId CreateRootBlobAndReturnId();
static cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CreateFsBlobStore(cpputils::unique_ref<blockstore::BlockStore2> blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation);
#ifndef CRYFS_NO_COMPATIBILITY
static cpputils::unique_ref<fsblobstore::FsBlobStore> MigrateOrCreateFsBlobStore(cpputils::unique_ref<blobstore::BlobStore> blobStore, CryConfigFile *configFile);

View File

@ -21,7 +21,7 @@ namespace bf = boost::filesystem;
using std::string;
using std::vector;
using blockstore::Key;
using blockstore::BlockId;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
@ -31,8 +31,8 @@ using cryfs::parallelaccessfsblobstore::DirBlobRef;
namespace cryfs {
CryDir::CryDir(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const Key &key)
: CryNode(device, std::move(parent), std::move(grandparent), key) {
CryDir::CryDir(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CryDir::~CryDir() {
@ -42,12 +42,12 @@ unique_ref<fspp::OpenFile> CryDir::createAndOpenFile(const string &name, mode_t
device()->callFsActionCallbacks();
if (!isRootDir()) {
//TODO Instead of doing nothing when we're the root directory, handle timestamps in the root dir correctly (and delete isRootDir() function)
parent()->updateModificationTimestampForChild(key());
parent()->updateModificationTimestampForChild(blockId());
}
auto child = device()->CreateFileBlob(key());
auto child = device()->CreateFileBlob(blockId());
auto now = cpputils::time::now();
auto dirBlob = LoadBlob();
dirBlob->AddChildFile(name, child->key(), mode, uid, gid, now, now);
dirBlob->AddChildFile(name, child->blockId(), mode, uid, gid, now, now);
return make_unique_ref<CryOpenFile>(device(), std::move(dirBlob), std::move(child));
}
@ -55,12 +55,12 @@ void CryDir::createDir(const string &name, mode_t mode, uid_t uid, gid_t gid) {
device()->callFsActionCallbacks();
if (!isRootDir()) {
//TODO Instead of doing nothing when we're the root directory, handle timestamps in the root dir correctly (and delete isRootDir() function)
parent()->updateModificationTimestampForChild(key());
parent()->updateModificationTimestampForChild(blockId());
}
auto blob = LoadBlob();
auto child = device()->CreateDirBlob(key());
auto child = device()->CreateDirBlob(blockId());
auto now = cpputils::time::now();
blob->AddChildDir(name, child->key(), mode, uid, gid, now, now);
blob->AddChildDir(name, child->blockId(), mode, uid, gid, now, now);
}
unique_ref<DirBlobRef> CryDir::LoadBlob() const {
@ -74,7 +74,7 @@ unique_ref<vector<fspp::Dir::Entry>> CryDir::children() {
device()->callFsActionCallbacks();
if (!isRootDir()) {
//TODO Instead of doing nothing when we're the root directory, handle timestamps in the root dir correctly (and delete isRootDir() function)
parent()->updateAccessTimestampForChild(key(), fsblobstore::TimestampUpdateBehavior::RELATIME);
parent()->updateAccessTimestampForChild(blockId(), fsblobstore::TimestampUpdateBehavior::RELATIME);
}
auto children = make_unique_ref<vector<fspp::Dir::Entry>>();
children->push_back(fspp::Dir::Entry(fspp::Dir::EntryType::DIR, "."));
@ -93,19 +93,19 @@ void CryDir::createSymlink(const string &name, const bf::path &target, uid_t uid
device()->callFsActionCallbacks();
if (!isRootDir()) {
//TODO Instead of doing nothing when we're the root directory, handle timestamps in the root dir correctly (and delete isRootDir() function)
parent()->updateModificationTimestampForChild(key());
parent()->updateModificationTimestampForChild(blockId());
}
auto blob = LoadBlob();
auto child = device()->CreateSymlinkBlob(target, key());
auto child = device()->CreateSymlinkBlob(target, blockId());
auto now = cpputils::time::now();
blob->AddChildSymlink(name, child->key(), uid, gid, now, now);
blob->AddChildSymlink(name, child->blockId(), uid, gid, now, now);
}
void CryDir::remove() {
device()->callFsActionCallbacks();
if (grandparent() != none) {
//TODO Instead of doing nothing when we're in the root directory, handle timestamps in the root dir correctly
(*grandparent())->updateModificationTimestampForChild(parent()->key());
(*grandparent())->updateModificationTimestampForChild(parent()->blockId());
}
{
auto blob = LoadBlob();

View File

@ -10,7 +10,7 @@ namespace cryfs {
class CryDir final: public fspp::Dir, public CryNode {
public:
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::Key &key);
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CryDir();
//TODO return type variance to CryFile/CryDir?

View File

@ -10,7 +10,7 @@ namespace bf = boost::filesystem;
using fspp::fuse::CHECK_RETVAL;
using fspp::fuse::FuseErrnoException;
using blockstore::Key;
using blockstore::BlockId;
using boost::none;
using boost::optional;
using cpputils::unique_ref;
@ -21,8 +21,8 @@ using cryfs::parallelaccessfsblobstore::FileBlobRef;
namespace cryfs {
CryFile::CryFile(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const Key &key)
: CryNode(device, std::move(parent), std::move(grandparent), key) {
CryFile::CryFile(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CryFile::~CryFile() {
@ -47,7 +47,7 @@ void CryFile::truncate(off_t size) {
device()->callFsActionCallbacks();
auto blob = LoadBlob();
blob->resize(size);
parent()->updateModificationTimestampForChild(key());
parent()->updateModificationTimestampForChild(blockId());
}
fspp::Dir::EntryType CryFile::getType() const {
@ -59,7 +59,7 @@ void CryFile::remove() {
device()->callFsActionCallbacks();
if (grandparent() != none) {
//TODO Instead of doing nothing when we're in the root directory, handle timestamps in the root dir correctly
(*grandparent())->updateModificationTimestampForChild(parent()->key());
(*grandparent())->updateModificationTimestampForChild(parent()->blockId());
}
removeNode();
}

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CryFile final: public fspp::File, public CryNode {
public:
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::Key &key);
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CryFile();
cpputils::unique_ref<fspp::OpenFile> open(int flags) override;

View File

@ -13,7 +13,7 @@
namespace bf = boost::filesystem;
using blockstore::Key;
using blockstore::BlockId;
using blobstore::Blob;
using cpputils::dynamic_pointer_move;
using cpputils::unique_ref;
@ -30,11 +30,11 @@ using fspp::fuse::FuseErrnoException;
namespace cryfs {
CryNode::CryNode(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const Key &key)
CryNode::CryNode(CryDevice *device, optional<unique_ref<DirBlobRef>> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: _device(device),
_parent(none),
_grandparent(none),
_key(key) {
_blockId(blockId) {
ASSERT(parent != none || grandparent == none, "Grandparent can only be set when parent is not none");
@ -85,24 +85,24 @@ void CryNode::rename(const bf::path &to) {
auto targetDir = std::move(targetDirWithParent.blob);
auto targetDirParent = std::move(targetDirWithParent.parent);
auto old = (*_parent)->GetChild(_key);
auto old = (*_parent)->GetChild(_blockId);
if (old == boost::none) {
throw FuseErrnoException(EIO);
}
fsblobstore::DirEntry oldEntry = *old; // Copying this (instead of only keeping the reference) is necessary, because the operations below (i.e. RenameChild()) might make a reference invalid.
auto onOverwritten = [this] (const blockstore::Key &key) {
device()->RemoveBlob(key);
auto onOverwritten = [this] (const blockstore::BlockId &blockId) {
device()->RemoveBlob(blockId);
};
_updateParentModificationTimestamp();
if (targetDir->key() == (*_parent)->key()) {
targetDir->RenameChild(oldEntry.key(), to.filename().native(), onOverwritten);
if (targetDir->blockId() == (*_parent)->blockId()) {
targetDir->RenameChild(oldEntry.blockId(), to.filename().native(), onOverwritten);
} else {
_updateTargetDirModificationTimestamp(*targetDir, std::move(targetDirParent));
targetDir->AddOrOverwriteChild(to.filename().native(), oldEntry.key(), oldEntry.type(), oldEntry.mode(), oldEntry.uid(), oldEntry.gid(),
targetDir->AddOrOverwriteChild(to.filename().native(), oldEntry.blockId(), oldEntry.type(), oldEntry.mode(), oldEntry.uid(), oldEntry.gid(),
oldEntry.lastAccessTime(), oldEntry.lastModificationTime(), onOverwritten);
(*_parent)->RemoveChild(oldEntry.name());
// targetDir is now the new parent for this node. Adapt to it, so we can call further operations on this node object.
LoadBlob()->setParentPointer(targetDir->key());
LoadBlob()->setParentPointer(targetDir->blockId());
_parent = std::move(targetDir);
}
}
@ -111,14 +111,14 @@ void CryNode::_updateParentModificationTimestamp() {
if (_grandparent != none) {
// TODO Handle timestamps of the root directory (_grandparent == none) correctly.
ASSERT(_parent != none, "Grandparent is set, so also parent has to be set");
(*_grandparent)->updateModificationTimestampForChild((*_parent)->key());
(*_grandparent)->updateModificationTimestampForChild((*_parent)->blockId());
}
}
void CryNode::_updateTargetDirModificationTimestamp(const DirBlobRef &targetDir, optional<unique_ref<DirBlobRef>> targetDirParent) {
if (targetDirParent != none) {
// TODO Handle timestamps of the root directory (targetDirParent == none) correctly.
(*targetDirParent)->updateModificationTimestampForChild(targetDir.key());
(*targetDirParent)->updateModificationTimestampForChild(targetDir.blockId());
}
}
@ -130,7 +130,7 @@ void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) {
//TODO What should we do?
throw FuseErrnoException(EIO);
}
(*_parent)->utimensChild(_key, lastAccessTime, lastModificationTime);
(*_parent)->utimensChild(_blockId, lastAccessTime, lastModificationTime);
}
void CryNode::removeNode() {
@ -140,8 +140,8 @@ void CryNode::removeNode() {
//TODO What should we do?
throw FuseErrnoException(EIO);
}
(*_parent)->RemoveChild(_key);
_device->RemoveBlob(_key);
(*_parent)->RemoveChild(_blockId);
_device->RemoveBlob(_blockId);
}
CryDevice *CryNode::device() {
@ -153,13 +153,13 @@ const CryDevice *CryNode::device() const {
}
unique_ref<FsBlobRef> CryNode::LoadBlob() const {
auto blob = _device->LoadBlob(_key);
ASSERT(_parent == none || blob->parentPointer() == (*_parent)->key(), "Blob has wrong parent pointer.");
auto blob = _device->LoadBlob(_blockId);
ASSERT(_parent == none || blob->parentPointer() == (*_parent)->blockId(), "Blob has wrong parent pointer.");
return blob;
}
const blockstore::Key &CryNode::key() const {
return _key;
const blockstore::BlockId &CryNode::blockId() const {
return _blockId;
}
void CryNode::stat(struct ::stat *result) const {
@ -179,7 +179,7 @@ void CryNode::stat(struct ::stat *result) const {
result->st_mtim = now;
result->st_ctim = now;
} else {
(*_parent)->statChild(_key, result);
(*_parent)->statChild(_blockId, result);
}
}
@ -190,7 +190,7 @@ void CryNode::chmod(mode_t mode) {
//TODO What should we do?
throw FuseErrnoException(EIO);
}
(*_parent)->chmodChild(_key, mode);
(*_parent)->chmodChild(_blockId, mode);
}
void CryNode::chown(uid_t uid, gid_t gid) {
@ -200,15 +200,15 @@ void CryNode::chown(uid_t uid, gid_t gid) {
//TODO What should we do?
throw FuseErrnoException(EIO);
}
(*_parent)->chownChild(_key, uid, gid);
(*_parent)->chownChild(_blockId, uid, gid);
}
bool CryNode::checkParentPointer() {
auto parentPointer = LoadBlob()->parentPointer();
if (_parent == none) {
return parentPointer == Key::Null();
return parentPointer == BlockId::Null();
} else {
return parentPointer == (*_parent)->key();
return parentPointer == (*_parent)->blockId();
}
}

View File

@ -15,7 +15,7 @@ public:
virtual ~CryNode();
// TODO grandparent is only needed to set the timestamps of the parent directory on rename and remove. Delete grandparent parameter once we store timestamps in the blob itself instead of in the directory listing.
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::Key &key);
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
void access(int mask) const override;
void stat(struct ::stat *result) const override;
void chmod(mode_t mode) override;
@ -31,7 +31,7 @@ protected:
CryDevice *device();
const CryDevice *device() const;
const blockstore::Key &key() const;
const blockstore::BlockId &blockId() const;
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob() const;
bool isRootDir() const;
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent() const;
@ -49,7 +49,7 @@ private:
CryDevice *_device;
boost::optional<std::shared_ptr<parallelaccessfsblobstore::DirBlobRef>> _parent;
boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> _grandparent;
blockstore::Key _key;
blockstore::BlockId _blockId;
DISALLOW_COPY_AND_ASSIGN(CryNode);
};

View File

@ -36,24 +36,24 @@ void CryOpenFile::flush() {
void CryOpenFile::stat(struct ::stat *result) const {
_device->callFsActionCallbacks();
result->st_size = _fileBlob->size();
_parent->statChildWithSizeAlreadySet(_fileBlob->key(), result);
_parent->statChildWithSizeAlreadySet(_fileBlob->blockId(), result);
}
void CryOpenFile::truncate(off_t size) const {
_device->callFsActionCallbacks();
_fileBlob->resize(size);
_parent->updateModificationTimestampForChild(_fileBlob->key());
_parent->updateModificationTimestampForChild(_fileBlob->blockId());
}
size_t CryOpenFile::read(void *buf, size_t count, off_t offset) const {
_device->callFsActionCallbacks();
_parent->updateAccessTimestampForChild(_fileBlob->key(), fsblobstore::TimestampUpdateBehavior::RELATIME);
_parent->updateAccessTimestampForChild(_fileBlob->blockId(), fsblobstore::TimestampUpdateBehavior::RELATIME);
return _fileBlob->read(buf, offset, count);
}
void CryOpenFile::write(const void *buf, size_t count, off_t offset) {
_device->callFsActionCallbacks();
_parent->updateModificationTimestampForChild(_fileBlob->key());
_parent->updateModificationTimestampForChild(_fileBlob->blockId());
_fileBlob->write(buf, offset, count);
}

View File

@ -15,7 +15,7 @@ namespace bf = boost::filesystem;
using std::string;
using std::vector;
using blockstore::Key;
using blockstore::BlockId;
using boost::none;
using boost::optional;
using cpputils::unique_ref;
@ -26,8 +26,8 @@ using cryfs::parallelaccessfsblobstore::DirBlobRef;
namespace cryfs {
CrySymlink::CrySymlink(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const Key &key)
: CryNode(device, std::move(parent), std::move(grandparent), key) {
CrySymlink::CrySymlink(CryDevice *device, unique_ref<DirBlobRef> parent, optional<unique_ref<DirBlobRef>> grandparent, const BlockId &blockId)
: CryNode(device, std::move(parent), std::move(grandparent), blockId) {
}
CrySymlink::~CrySymlink() {
@ -47,7 +47,7 @@ fspp::Dir::EntryType CrySymlink::getType() const {
bf::path CrySymlink::target() {
device()->callFsActionCallbacks();
parent()->updateAccessTimestampForChild(key(), fsblobstore::TimestampUpdateBehavior::RELATIME);
parent()->updateAccessTimestampForChild(blockId(), fsblobstore::TimestampUpdateBehavior::RELATIME);
auto blob = LoadBlob();
return blob->target();
}
@ -56,7 +56,7 @@ void CrySymlink::remove() {
device()->callFsActionCallbacks();
if (grandparent() != none) {
//TODO Instead of doing nothing when we're in the root directory, handle timestamps in the root dir correctly
(*grandparent())->updateModificationTimestampForChild(parent()->key());
(*grandparent())->updateModificationTimestampForChild(parent()->blockId());
}
removeNode();
}

View File

@ -11,7 +11,7 @@ namespace cryfs {
class CrySymlink final: public fspp::Symlink, public CryNode {
public:
CrySymlink(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::Key &key);
CrySymlink(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, boost::optional<cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef>> grandparent, const blockstore::BlockId &blockId);
~CrySymlink();
boost::filesystem::path target() override;

View File

@ -6,7 +6,7 @@ using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
using blobstore::BlobStore;
using blockstore::Key;
using blockstore::BlockId;
using boost::optional;
using boost::none;
using std::function;
@ -19,12 +19,12 @@ using cryfs::fsblobstore::SymlinkBlob;
namespace cryfs {
namespace cachingfsblobstore {
optional<unique_ref<FsBlobRef>> CachingFsBlobStore::load(const Key &key) {
auto fromCache = _cache.pop(key);
optional<unique_ref<FsBlobRef>> CachingFsBlobStore::load(const BlockId &blockId) {
auto fromCache = _cache.pop(blockId);
if (fromCache != none) {
return _makeRef(std::move(*fromCache));
}
auto fromBaseStore = _baseBlobStore->load(key);
auto fromBaseStore = _baseBlobStore->load(blockId);
if (fromBaseStore != none) {
return _makeRef(std::move(*fromBaseStore));
}

View File

@ -19,12 +19,12 @@ namespace cryfs {
CachingFsBlobStore(cpputils::unique_ref<fsblobstore::FsBlobStore> baseBlobStore);
~CachingFsBlobStore();
cpputils::unique_ref<FileBlobRef> createFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<DirBlobRef> createDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
boost::optional<cpputils::unique_ref<FsBlobRef>> load(const blockstore::Key &key);
cpputils::unique_ref<FileBlobRef> createFileBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<DirBlobRef> createDirBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::BlockId &parent);
boost::optional<cpputils::unique_ref<FsBlobRef>> load(const blockstore::BlockId &blockId);
void remove(cpputils::unique_ref<FsBlobRef> blob);
void remove(const blockstore::Key &key);
void remove(const blockstore::BlockId &blockId);
uint64_t virtualBlocksizeBytes() const;
uint64_t numBlocks() const;
uint64_t estimateSpaceForNumBlocksLeft() const;
@ -38,7 +38,7 @@ namespace cryfs {
//TODO Move Cache to some common location, not in blockstore
//TODO Use other cache config (i.e. smaller max number of entries) here than in blockstore
blockstore::caching::Cache<blockstore::Key, cpputils::unique_ref<fsblobstore::FsBlob>, 50> _cache;
blockstore::caching::Cache<blockstore::BlockId, cpputils::unique_ref<fsblobstore::FsBlob>, 50> _cache;
DISALLOW_COPY_AND_ASSIGN(CachingFsBlobStore);
};
@ -51,21 +51,21 @@ namespace cryfs {
inline CachingFsBlobStore::~CachingFsBlobStore() {
}
inline cpputils::unique_ref<FileBlobRef> CachingFsBlobStore::createFileBlob(const blockstore::Key &parent) {
inline cpputils::unique_ref<FileBlobRef> CachingFsBlobStore::createFileBlob(const blockstore::BlockId &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
return cpputils::make_unique_ref<FileBlobRef>(_baseBlobStore->createFileBlob(parent), this);
}
inline cpputils::unique_ref<DirBlobRef> CachingFsBlobStore::createDirBlob(const blockstore::Key &parent) {
inline cpputils::unique_ref<DirBlobRef> CachingFsBlobStore::createDirBlob(const blockstore::BlockId &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
return cpputils::make_unique_ref<DirBlobRef>(_baseBlobStore->createDirBlob(parent), this);
}
inline cpputils::unique_ref<SymlinkBlobRef> CachingFsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent) {
inline cpputils::unique_ref<SymlinkBlobRef> CachingFsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::BlockId &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
@ -77,18 +77,18 @@ namespace cryfs {
return _baseBlobStore->remove(std::move(baseBlob));
}
inline void CachingFsBlobStore::remove(const blockstore::Key &key) {
auto fromCache = _cache.pop(key);
inline void CachingFsBlobStore::remove(const blockstore::BlockId &blockId) {
auto fromCache = _cache.pop(blockId);
if (fromCache != boost::none) {
remove(_makeRef(std::move(*fromCache)));
} else {
_baseBlobStore->remove(key);
_baseBlobStore->remove(blockId);
}
}
inline void CachingFsBlobStore::releaseForCache(cpputils::unique_ref<fsblobstore::FsBlob> baseBlob) {
blockstore::Key key = baseBlob->key();
_cache.push(key, std::move(baseBlob));
blockstore::BlockId blockId = baseBlob->blockId();
_cache.push(blockId, std::move(baseBlob));
}
inline uint64_t CachingFsBlobStore::virtualBlocksizeBytes() const {

View File

@ -23,16 +23,16 @@ public:
return _base->GetChild(name);
}
boost::optional<const Entry&> GetChild(const blockstore::Key &key) const {
return _base->GetChild(key);
boost::optional<const Entry&> GetChild(const blockstore::BlockId &blockId) const {
return _base->GetChild(blockId);
}
size_t NumChildren() const {
return _base->NumChildren();
}
void RemoveChild(const blockstore::Key &key) {
return _base->RemoveChild(key);
void RemoveChild(const blockstore::BlockId &blockId) {
return _base->RemoveChild(blockId);
}
void RemoveChild(const std::string &name) {
@ -43,69 +43,69 @@ public:
return _base->flush();
}
void AddOrOverwriteChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
void AddOrOverwriteChild(const std::string &name, const blockstore::BlockId &blobId, fspp::Dir::EntryType type,
mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
std::function<void (const blockstore::Key &key)> onOverwritten) {
return _base->AddOrOverwriteChild(name, blobKey, type, mode, uid, gid, lastAccessTime, lastModificationTime, onOverwritten);
std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
return _base->AddOrOverwriteChild(name, blobId, type, mode, uid, gid, lastAccessTime, lastModificationTime, onOverwritten);
}
void RenameChild(const blockstore::Key &key, const std::string &newName, std::function<void (const blockstore::Key &key)> onOverwritten) {
return _base->RenameChild(key, newName, onOverwritten);
void RenameChild(const blockstore::BlockId &blockId, const std::string &newName, std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
return _base->RenameChild(blockId, newName, onOverwritten);
}
void statChild(const blockstore::Key &key, struct ::stat *result) const {
return _base->statChild(key, result);
void statChild(const blockstore::BlockId &blockId, struct ::stat *result) const {
return _base->statChild(blockId, result);
}
void statChildWithSizeAlreadySet(const blockstore::Key &key, struct ::stat *result) const {
return _base->statChildWithSizeAlreadySet(key, result);
void statChildWithSizeAlreadySet(const blockstore::BlockId &blockId, struct ::stat *result) const {
return _base->statChildWithSizeAlreadySet(blockId, result);
}
void updateAccessTimestampForChild(const blockstore::Key &key, fsblobstore::TimestampUpdateBehavior timestampUpdateBehavior) {
return _base->updateAccessTimestampForChild(key, timestampUpdateBehavior);
void updateAccessTimestampForChild(const blockstore::BlockId &blockId, fsblobstore::TimestampUpdateBehavior timestampUpdateBehavior) {
return _base->updateAccessTimestampForChild(blockId, timestampUpdateBehavior);
}
void updateModificationTimestampForChild(const blockstore::Key &key) {
return _base->updateModificationTimestampForChild(key);
void updateModificationTimestampForChild(const blockstore::BlockId &blockId) {
return _base->updateModificationTimestampForChild(blockId);
}
void chmodChild(const blockstore::Key &key, mode_t mode) {
return _base->chmodChild(key, mode);
void chmodChild(const blockstore::BlockId &blockId, mode_t mode) {
return _base->chmodChild(blockId, mode);
}
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid) {
return _base->chownChild(key, uid, gid);
void chownChild(const blockstore::BlockId &blockId, uid_t uid, gid_t gid) {
return _base->chownChild(blockId, uid, gid);
}
void utimensChild(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime) {
return _base->utimensChild(key, lastAccessTime, lastModificationTime);
void utimensChild(const blockstore::BlockId &blockId, timespec lastAccessTime, timespec lastModificationTime) {
return _base->utimensChild(blockId, lastAccessTime, lastModificationTime);
}
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildDir(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
void AddChildDir(const std::string &name, const blockstore::BlockId &blobId, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildDir(name, blobId, mode, uid, gid, lastAccessTime, lastModificationTime);
}
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildFile(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
void AddChildFile(const std::string &name, const blockstore::BlockId &blobId, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildFile(name, blobId, mode, uid, gid, lastAccessTime, lastModificationTime);
}
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildSymlink(name, blobKey, uid, gid, lastAccessTime, lastModificationTime);
void AddChildSymlink(const std::string &name, const blockstore::BlockId &blobId, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildSymlink(name, blobId, uid, gid, lastAccessTime, lastModificationTime);
}
void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const {
return _base->AppendChildrenTo(result);
}
const blockstore::Key &key() const {
return _base->key();
const blockstore::BlockId &blockId() const {
return _base->blockId();
}
off_t lstat_size() const {
return _base->lstat_size();
}
void setLstatSizeGetter(std::function<off_t(const blockstore::Key&)> getLstatSize) {
void setLstatSizeGetter(std::function<off_t(const blockstore::BlockId&)> getLstatSize) {
return _base->setLstatSizeGetter(getLstatSize);
}

View File

@ -36,8 +36,8 @@ public:
return _base->flush();
}
const blockstore::Key &key() const {
return _base->key();
const blockstore::BlockId &blockId() const {
return _base->blockId();
}
off_t lstat_size() const {

View File

@ -12,15 +12,15 @@ class CachingFsBlobStore;
class FsBlobRef {
public:
virtual ~FsBlobRef();
virtual const blockstore::Key &key() const = 0;
virtual const blockstore::BlockId &blockId() const = 0;
virtual off_t lstat_size() const = 0;
const blockstore::Key &parentPointer() const {
const blockstore::BlockId &parentPointer() const {
return _baseBlob->parentPointer();
}
void setParentPointer(const blockstore::Key &parentKey) {
return _baseBlob->setParentPointer(parentKey);
void setParentPointer(const blockstore::BlockId &parentBlobId) {
return _baseBlob->setParentPointer(parentBlobId);
}
cpputils::unique_ref<fsblobstore::FsBlob> releaseBaseBlob() {

View File

@ -20,8 +20,8 @@ public:
return _base->target();
}
const blockstore::Key &key() const {
return _base->key();
const blockstore::BlockId &blockId() const {
return _base->blockId();
}
off_t lstat_size() const {

View File

@ -17,7 +17,7 @@ using std::pair;
using std::make_pair;
using blobstore::Blob;
using blockstore::Key;
using blockstore::BlockId;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
@ -28,7 +28,7 @@ namespace fsblobstore {
constexpr off_t DirBlob::DIR_LSTAT_SIZE;
DirBlob::DirBlob(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, std::function<off_t (const blockstore::Key&)> getLstatSize) :
DirBlob::DirBlob(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, std::function<off_t (const blockstore::BlockId&)> getLstatSize) :
FsBlob(std::move(blob)), _fsBlobStore(fsBlobStore), _getLstatSize(getLstatSize), _entries(), _mutex(), _changed(false) {
ASSERT(baseBlob().blobType() == FsBlobView::BlobType::DIR, "Loaded blob is not a directory");
_readEntriesFromBlob();
@ -45,7 +45,7 @@ void DirBlob::flush() {
baseBlob().flush();
}
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, const blockstore::Key &parent, std::function<off_t(const blockstore::Key&)> getLstatSize) {
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, const blockstore::BlockId &parent, std::function<off_t(const blockstore::BlockId&)> getLstatSize) {
InitializeBlob(blob.get(), FsBlobView::BlobType::DIR, parent);
return make_unique_ref<DirBlob>(fsBlobStore, std::move(blob), getLstatSize);
}
@ -65,38 +65,38 @@ void DirBlob::_readEntriesFromBlob() {
_entries.deserializeFrom(static_cast<uint8_t*>(data.data()), data.size());
}
void DirBlob::AddChildDir(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
void DirBlob::AddChildDir(const std::string &name, const BlockId &blobId, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
std::unique_lock<std::mutex> lock(_mutex);
_addChild(name, blobKey, fspp::Dir::EntryType::DIR, mode, uid, gid, lastAccessTime, lastModificationTime);
_addChild(name, blobId, fspp::Dir::EntryType::DIR, mode, uid, gid, lastAccessTime, lastModificationTime);
}
void DirBlob::AddChildFile(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
void DirBlob::AddChildFile(const std::string &name, const BlockId &blobId, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
std::unique_lock<std::mutex> lock(_mutex);
_addChild(name, blobKey, fspp::Dir::EntryType::FILE, mode, uid, gid, lastAccessTime, lastModificationTime);
_addChild(name, blobId, fspp::Dir::EntryType::FILE, mode, uid, gid, lastAccessTime, lastModificationTime);
}
void DirBlob::AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
void DirBlob::AddChildSymlink(const std::string &name, const blockstore::BlockId &blobId, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
std::unique_lock<std::mutex> lock(_mutex);
_addChild(name, blobKey, fspp::Dir::EntryType::SYMLINK, S_IFLNK | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH, uid, gid, lastAccessTime, lastModificationTime);
_addChild(name, blobId, fspp::Dir::EntryType::SYMLINK, S_IFLNK | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH, uid, gid, lastAccessTime, lastModificationTime);
}
void DirBlob::_addChild(const std::string &name, const Key &blobKey,
void DirBlob::_addChild(const std::string &name, const BlockId &blobId,
fspp::Dir::EntryType entryType, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
_entries.add(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_entries.add(name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_changed = true;
}
void DirBlob::AddOrOverwriteChild(const std::string &name, const Key &blobKey, fspp::Dir::EntryType entryType,
void DirBlob::AddOrOverwriteChild(const std::string &name, const BlockId &blobId, fspp::Dir::EntryType entryType,
mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
std::function<void (const blockstore::Key &key)> onOverwritten) {
std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.addOrOverwrite(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime, onOverwritten);
_entries.addOrOverwrite(name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime, onOverwritten);
_changed = true;
}
void DirBlob::RenameChild(const blockstore::Key &key, const std::string &newName, std::function<void (const blockstore::Key &key)> onOverwritten) {
void DirBlob::RenameChild(const blockstore::BlockId &blockId, const std::string &newName, std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.rename(key, newName, onOverwritten);
_entries.rename(blockId, newName, onOverwritten);
_changed = true;
}
@ -105,9 +105,9 @@ boost::optional<const DirEntry&> DirBlob::GetChild(const string &name) const {
return _entries.get(name);
}
boost::optional<const DirEntry&> DirBlob::GetChild(const Key &key) const {
boost::optional<const DirEntry&> DirBlob::GetChild(const BlockId &blockId) const {
std::unique_lock<std::mutex> lock(_mutex);
return _entries.get(key);
return _entries.get(blockId);
}
void DirBlob::RemoveChild(const string &name) {
@ -116,9 +116,9 @@ void DirBlob::RemoveChild(const string &name) {
_changed = true;
}
void DirBlob::RemoveChild(const Key &key) {
void DirBlob::RemoveChild(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.remove(key);
_entries.remove(blockId);
_changed = true;
}
@ -134,13 +134,13 @@ off_t DirBlob::lstat_size() const {
return DIR_LSTAT_SIZE;
}
void DirBlob::statChild(const Key &key, struct ::stat *result) const {
result->st_size = _getLstatSize(key);
statChildWithSizeAlreadySet(key, result);
void DirBlob::statChild(const BlockId &blockId, struct ::stat *result) const {
result->st_size = _getLstatSize(blockId);
statChildWithSizeAlreadySet(blockId, result);
}
void DirBlob::statChildWithSizeAlreadySet(const Key &key, struct ::stat *result) const {
auto childOpt = GetChild(key);
void DirBlob::statChildWithSizeAlreadySet(const BlockId &blockId, struct ::stat *result) const {
auto childOpt = GetChild(blockId);
if (childOpt == boost::none) {
throw fspp::fuse::FuseErrnoException(ENOENT);
}
@ -158,39 +158,39 @@ void DirBlob::statChildWithSizeAlreadySet(const Key &key, struct ::stat *result)
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
}
void DirBlob::updateAccessTimestampForChild(const Key &key, TimestampUpdateBehavior timestampUpdateBehavior) {
void DirBlob::updateAccessTimestampForChild(const BlockId &blockId, TimestampUpdateBehavior timestampUpdateBehavior) {
std::unique_lock<std::mutex> lock(_mutex);
if (_entries.updateAccessTimestampForChild(key, timestampUpdateBehavior)) {
if (_entries.updateAccessTimestampForChild(blockId, timestampUpdateBehavior)) {
_changed = true;
}
}
void DirBlob::updateModificationTimestampForChild(const Key &key) {
void DirBlob::updateModificationTimestampForChild(const BlockId &blockId) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.updateModificationTimestampForChild(key);
_entries.updateModificationTimestampForChild(blockId);
_changed = true;
}
void DirBlob::chmodChild(const Key &key, mode_t mode) {
void DirBlob::chmodChild(const BlockId &blockId, mode_t mode) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.setMode(key, mode);
_entries.setMode(blockId, mode);
_changed = true;
}
void DirBlob::chownChild(const Key &key, uid_t uid, gid_t gid) {
void DirBlob::chownChild(const BlockId &blockId, uid_t uid, gid_t gid) {
std::unique_lock<std::mutex> lock(_mutex);
if(_entries.setUidGid(key, uid, gid)) {
if(_entries.setUidGid(blockId, uid, gid)) {
_changed = true;
}
}
void DirBlob::utimensChild(const Key &key, timespec lastAccessTime, timespec lastModificationTime) {
void DirBlob::utimensChild(const BlockId &blockId, timespec lastAccessTime, timespec lastModificationTime) {
std::unique_lock<std::mutex> lock(_mutex);
_entries.setAccessTimes(key, lastAccessTime, lastModificationTime);
_entries.setAccessTimes(blockId, lastAccessTime, lastModificationTime);
_changed = true;
}
void DirBlob::setLstatSizeGetter(std::function<off_t(const blockstore::Key&)> getLstatSize) {
void DirBlob::setLstatSizeGetter(std::function<off_t(const blockstore::BlockId&)> getLstatSize) {
std::unique_lock<std::mutex> lock(_mutex);
_getLstatSize = getLstatSize;
}

View File

@ -2,7 +2,7 @@
#ifndef MESSMER_CRYFS_FILESYSTEM_FSBLOBSTORE_DIRBLOB_H_
#define MESSMER_CRYFS_FILESYSTEM_FSBLOBSTORE_DIRBLOB_H_
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <cpp-utils/macros.h>
#include <fspp/fs_interface/Dir.h>
#include "FsBlob.h"
@ -18,10 +18,10 @@ namespace cryfs {
constexpr static off_t DIR_LSTAT_SIZE = 4096;
static cpputils::unique_ref<DirBlob> InitializeEmptyDir(FsBlobStore *fsBlobStore, cpputils::unique_ref<blobstore::Blob> blob,
const blockstore::Key &parent,
std::function<off_t (const blockstore::Key&)> getLstatSize);
const blockstore::BlockId &parent,
std::function<off_t (const blockstore::BlockId&)> getLstatSize);
DirBlob(FsBlobStore *fsBlobStore, cpputils::unique_ref<blobstore::Blob> blob, std::function<off_t (const blockstore::Key&)> getLstatSize);
DirBlob(FsBlobStore *fsBlobStore, cpputils::unique_ref<blobstore::Blob> blob, std::function<off_t (const blockstore::BlockId&)> getLstatSize);
~DirBlob();
@ -34,47 +34,47 @@ namespace cryfs {
boost::optional<const DirEntry&> GetChild(const std::string &name) const;
boost::optional<const DirEntry&> GetChild(const blockstore::Key &key) const;
boost::optional<const DirEntry&> GetChild(const blockstore::BlockId &blobId) const;
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
void AddChildDir(const std::string &name, const blockstore::BlockId &blobId, mode_t mode, uid_t uid,
gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
void AddChildFile(const std::string &name, const blockstore::BlockId &blobId, mode_t mode, uid_t uid,
gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChildSymlink(const std::string &name, const blockstore::BlockId &blobId, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddOrOverwriteChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
void AddOrOverwriteChild(const std::string &name, const blockstore::BlockId &blobId, fspp::Dir::EntryType type,
mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
std::function<void (const blockstore::Key &key)> onOverwritten);
std::function<void (const blockstore::BlockId &blockId)> onOverwritten);
void RenameChild(const blockstore::Key &key, const std::string &newName, std::function<void (const blockstore::Key &key)> onOverwritten);
void RenameChild(const blockstore::BlockId &blockId, const std::string &newName, std::function<void (const blockstore::BlockId &blockId)> onOverwritten);
void RemoveChild(const std::string &name);
void RemoveChild(const blockstore::Key &key);
void RemoveChild(const blockstore::BlockId &blockId);
void flush();
void statChild(const blockstore::Key &key, struct ::stat *result) const;
void statChild(const blockstore::BlockId &blockId, struct ::stat *result) const;
void statChildWithSizeAlreadySet(const blockstore::Key &key, struct ::stat *result) const;
void statChildWithSizeAlreadySet(const blockstore::BlockId &blockId, struct ::stat *result) const;
void updateAccessTimestampForChild(const blockstore::Key &key, TimestampUpdateBehavior timestampUpdateBehavior);
void updateAccessTimestampForChild(const blockstore::BlockId &blockId, TimestampUpdateBehavior timestampUpdateBehavior);
void updateModificationTimestampForChild(const blockstore::Key &key);
void updateModificationTimestampForChild(const blockstore::BlockId &blockId);
void chmodChild(const blockstore::Key &key, mode_t mode);
void chmodChild(const blockstore::BlockId &blockId, mode_t mode);
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
void chownChild(const blockstore::BlockId &blockId, uid_t uid, gid_t gid);
void utimensChild(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime);
void utimensChild(const blockstore::BlockId &blockId, timespec lastAccessTime, timespec lastModificationTime);
void setLstatSizeGetter(std::function<off_t(const blockstore::Key&)> getLstatSize);
void setLstatSizeGetter(std::function<off_t(const blockstore::BlockId&)> getLstatSize);
private:
void _addChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
void _addChild(const std::string &name, const blockstore::BlockId &blobId, fspp::Dir::EntryType type,
mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void _readEntriesFromBlob();
void _writeEntriesToBlob();
@ -82,7 +82,7 @@ namespace cryfs {
cpputils::unique_ref<blobstore::Blob> releaseBaseBlob() override;
FsBlobStore *_fsBlobStore;
std::function<off_t (const blockstore::Key&)> _getLstatSize;
std::function<off_t (const blockstore::BlockId&)> _getLstatSize;
DirEntryList _entries;
mutable std::mutex _mutex;
bool _changed;

View File

@ -1,12 +1,12 @@
#include "FileBlob.h"
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <cassert>
using blobstore::Blob;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using blockstore::Key;
using blockstore::BlockId;
namespace cryfs {
namespace fsblobstore {
@ -16,7 +16,7 @@ FileBlob::FileBlob(unique_ref<Blob> blob)
ASSERT(baseBlob().blobType() == FsBlobView::BlobType::FILE, "Loaded blob is not a file");
}
unique_ref<FileBlob> FileBlob::InitializeEmptyFile(unique_ref<Blob> blob, const blockstore::Key &parent) {
unique_ref<FileBlob> FileBlob::InitializeEmptyFile(unique_ref<Blob> blob, const blockstore::BlockId &parent) {
InitializeBlob(blob.get(), FsBlobView::BlobType::FILE, parent);
return make_unique_ref<FileBlob>(std::move(blob));
}

View File

@ -9,7 +9,7 @@ namespace cryfs {
class FileBlob final: public FsBlob {
public:
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob, const blockstore::Key &parent);
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob, const blockstore::BlockId &parent);
FileBlob(cpputils::unique_ref<blobstore::Blob> blob);

View File

@ -13,9 +13,9 @@ namespace cryfs {
virtual ~FsBlob();
virtual off_t lstat_size() const = 0;
const blockstore::Key &key() const;
const blockstore::Key &parentPointer() const;
void setParentPointer(const blockstore::Key &parentKey);
const blockstore::BlockId &blockId() const;
const blockstore::BlockId &parentPointer() const;
void setParentPointer(const blockstore::BlockId &parentId);
protected:
FsBlob(cpputils::unique_ref<blobstore::Blob> baseBlob);
@ -23,7 +23,7 @@ namespace cryfs {
FsBlobView &baseBlob();
const FsBlobView &baseBlob() const;
static void InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::Key &parent);
static void InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::BlockId &parent);
friend class FsBlobStore;
virtual cpputils::unique_ref<blobstore::Blob> releaseBaseBlob();
@ -47,8 +47,8 @@ namespace cryfs {
inline FsBlob::~FsBlob() {
}
inline const blockstore::Key &FsBlob::key() const {
return _baseBlob.key();
inline const blockstore::BlockId &FsBlob::blockId() const {
return _baseBlob.blockId();
}
inline const FsBlobView &FsBlob::baseBlob() const {
@ -59,7 +59,7 @@ namespace cryfs {
return _baseBlob;
}
inline void FsBlob::InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::Key &parent) {
inline void FsBlob::InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::BlockId &parent) {
FsBlobView::InitializeBlob(blob, magicNumber, parent);
}
@ -67,12 +67,12 @@ namespace cryfs {
return _baseBlob.releaseBaseBlob();
}
inline const blockstore::Key &FsBlob::parentPointer() const {
inline const blockstore::BlockId &FsBlob::parentPointer() const {
return _baseBlob.parentPointer();
}
inline void FsBlob::setParentPointer(const blockstore::Key &parentKey) {
return _baseBlob.setParentPointer(parentKey);
inline void FsBlob::setParentPointer(const blockstore::BlockId &parentId) {
return _baseBlob.setParentPointer(parentId);
}
}
}

View File

@ -7,7 +7,7 @@ namespace bf = boost::filesystem;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using blobstore::BlobStore;
using blockstore::Key;
using blockstore::BlockId;
using boost::none;
using std::function;
using std::vector;
@ -15,8 +15,8 @@ using std::vector;
namespace cryfs {
namespace fsblobstore {
boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key) {
auto blob = _baseBlobStore->load(key);
boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::BlockId &blockId) {
auto blob = _baseBlobStore->load(blockId);
if (blob == none) {
return none;
}
@ -33,8 +33,8 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key
}
#ifndef CRYFS_NO_COMPATIBILITY
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::Key &rootKey) {
auto rootBlob = blobStore->load(rootKey);
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
auto rootBlob = blobStore->load(rootBlobId);
ASSERT(rootBlob != none, "Could not load root blob");
uint16_t format = FsBlobView::getFormatVersionHeader(**rootBlob);
@ -42,14 +42,14 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key
if (format == 0) {
// migration needed
std::cout << "Migrating file system for conflict resolution features. Please don't interrupt this process. This can take a while..." << std::flush;
fsBlobStore->_migrate(std::move(*rootBlob), blockstore::Key::Null());
fsBlobStore->_migrate(std::move(*rootBlob), blockstore::BlockId::Null());
std::cout << "done" << std::endl;
}
return fsBlobStore;
}
void FsBlobStore::_migrate(unique_ref<blobstore::Blob> node, const blockstore::Key &parentKey) {
FsBlobView::migrate(node.get(), parentKey);
void FsBlobStore::_migrate(unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId) {
FsBlobView::migrate(node.get(), parentId);
if (FsBlobView::blobType(*node) == FsBlobView::BlobType::DIR) {
DirBlob dir(this, std::move(node), _getLstatSize());
vector<fspp::Dir::Entry> children;
@ -57,9 +57,9 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key
for (const auto &child : children) {
auto childEntry = dir.GetChild(child.name);
ASSERT(childEntry != none, "Couldn't load child, although it was returned as a child in the lsit.");
auto childBlob = _baseBlobStore->load(childEntry->key());
auto childBlob = _baseBlobStore->load(childEntry->blockId());
ASSERT(childBlob != none, "Couldn't load child blob");
_migrate(std::move(*childBlob), dir.key());
_migrate(std::move(*childBlob), dir.blockId());
}
}
}

View File

@ -17,28 +17,28 @@ namespace cryfs {
public:
FsBlobStore(cpputils::unique_ref<blobstore::BlobStore> baseBlobStore);
cpputils::unique_ref<FileBlob> createFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<DirBlob> createDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<SymlinkBlob> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
boost::optional<cpputils::unique_ref<FsBlob>> load(const blockstore::Key &key);
cpputils::unique_ref<FileBlob> createFileBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<DirBlob> createDirBlob(const blockstore::BlockId &parent);
cpputils::unique_ref<SymlinkBlob> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::BlockId &parent);
boost::optional<cpputils::unique_ref<FsBlob>> load(const blockstore::BlockId &blockId);
void remove(cpputils::unique_ref<FsBlob> blob);
void remove(const blockstore::Key &key);
void remove(const blockstore::BlockId &blockId);
uint64_t numBlocks() const;
uint64_t estimateSpaceForNumBlocksLeft() const;
uint64_t virtualBlocksizeBytes() const;
#ifndef CRYFS_NO_COMPATIBILITY
static cpputils::unique_ref<FsBlobStore> migrateIfNeeded(cpputils::unique_ref<blobstore::BlobStore> blobStore, const blockstore::Key &rootKey);
static cpputils::unique_ref<FsBlobStore> migrateIfNeeded(cpputils::unique_ref<blobstore::BlobStore> blobStore, const blockstore::BlockId &blockId);
#endif
private:
#ifndef CRYFS_NO_COMPATIBILITY
void _migrate(cpputils::unique_ref<blobstore::Blob> node, const blockstore::Key &parentKey);
void _migrate(cpputils::unique_ref<blobstore::Blob> node, const blockstore::BlockId &parentId);
#endif
std::function<off_t(const blockstore::Key &)> _getLstatSize();
std::function<off_t(const blockstore::BlockId &)> _getLstatSize();
cpputils::unique_ref<blobstore::BlobStore> _baseBlobStore;
@ -49,17 +49,17 @@ namespace cryfs {
: _baseBlobStore(std::move(baseBlobStore)) {
}
inline cpputils::unique_ref<FileBlob> FsBlobStore::createFileBlob(const blockstore::Key &parent) {
inline cpputils::unique_ref<FileBlob> FsBlobStore::createFileBlob(const blockstore::BlockId &parent) {
auto blob = _baseBlobStore->create();
return FileBlob::InitializeEmptyFile(std::move(blob), parent);
}
inline cpputils::unique_ref<DirBlob> FsBlobStore::createDirBlob(const blockstore::Key &parent) {
inline cpputils::unique_ref<DirBlob> FsBlobStore::createDirBlob(const blockstore::BlockId &parent) {
auto blob = _baseBlobStore->create();
return DirBlob::InitializeEmptyDir(this, std::move(blob), parent, _getLstatSize());
}
inline cpputils::unique_ref<SymlinkBlob> FsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent) {
inline cpputils::unique_ref<SymlinkBlob> FsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::BlockId &parent) {
auto blob = _baseBlobStore->create();
return SymlinkBlob::InitializeSymlink(std::move(blob), target, parent);
}
@ -76,13 +76,13 @@ namespace cryfs {
_baseBlobStore->remove(blob->releaseBaseBlob());
}
inline void FsBlobStore::remove(const blockstore::Key &key) {
_baseBlobStore->remove(key);
inline void FsBlobStore::remove(const blockstore::BlockId &blockId) {
_baseBlobStore->remove(blockId);
}
inline std::function<off_t (const blockstore::Key &)> FsBlobStore::_getLstatSize() {
return [this] (const blockstore::Key &key) {
auto blob = load(key);
inline std::function<off_t (const blockstore::BlockId &)> FsBlobStore::_getLstatSize() {
return [this] (const blockstore::BlockId &blockId) {
auto blob = load(blockId);
ASSERT(blob != boost::none, "Blob not found");
return (*blob)->lstat_size();
};

View File

@ -7,16 +7,16 @@ namespace cryfs {
constexpr unsigned int FsBlobView::HEADER_SIZE;
#ifndef CRYFS_NO_COMPATIBILITY
void FsBlobView::migrate(blobstore::Blob *blob, const blockstore::Key &parentKey) {
void FsBlobView::migrate(blobstore::Blob *blob, const blockstore::BlockId &parentId) {
constexpr unsigned int OLD_HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t);
ASSERT(FsBlobView::getFormatVersionHeader(*blob) == 0, "Block already migrated");
// Resize blob and move data back
cpputils::Data data = blob->readAll();
blob->resize(blob->size() + blockstore::Key::BINARY_LENGTH);
blob->resize(blob->size() + blockstore::BlockId::BINARY_LENGTH);
blob->write(data.dataOffset(OLD_HEADER_SIZE), HEADER_SIZE, data.size() - OLD_HEADER_SIZE);
// Write parent pointer
blob->write(parentKey.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
blob->write(parentId.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::BlockId::BINARY_LENGTH);
// Update format version number
blob->write(&FORMAT_VERSION_HEADER, 0, sizeof(FORMAT_VERSION_HEADER));
}

View File

@ -17,18 +17,18 @@ namespace cryfs {
SYMLINK = 0x02
};
FsBlobView(cpputils::unique_ref<blobstore::Blob> baseBlob): _baseBlob(std::move(baseBlob)), _parentPointer(blockstore::Key::Null()) {
FsBlobView(cpputils::unique_ref<blobstore::Blob> baseBlob): _baseBlob(std::move(baseBlob)), _parentPointer(blockstore::BlockId::Null()) {
_checkHeader(*_baseBlob);
_loadParentPointer();
}
static void InitializeBlob(blobstore::Blob *baseBlob, BlobType blobType, const blockstore::Key &parent) {
static void InitializeBlob(blobstore::Blob *baseBlob, BlobType blobType, const blockstore::BlockId &parent) {
baseBlob->resize(sizeof(FORMAT_VERSION_HEADER) + 1);
baseBlob->write(&FORMAT_VERSION_HEADER, 0, sizeof(FORMAT_VERSION_HEADER));
uint8_t blobTypeInt = static_cast<uint8_t>(blobType);
baseBlob->write(&blobTypeInt, sizeof(FORMAT_VERSION_HEADER), sizeof(uint8_t));
baseBlob->write(parent.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
static_assert(HEADER_SIZE == sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::Key::BINARY_LENGTH, "If this fails, the header is not initialized correctly in this function.");
baseBlob->write(parent.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::BlockId::BINARY_LENGTH);
static_assert(HEADER_SIZE == sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::BlockId::BINARY_LENGTH, "If this fails, the header is not initialized correctly in this function.");
}
static BlobType blobType(const blobstore::Blob &blob) {
@ -40,17 +40,17 @@ namespace cryfs {
return _blobType(*_baseBlob);
}
const blockstore::Key &parentPointer() const {
const blockstore::BlockId &parentPointer() const {
return _parentPointer;
}
void setParentPointer(const blockstore::Key &parentKey) {
_parentPointer = parentKey;
void setParentPointer(const blockstore::BlockId &parentId) {
_parentPointer = parentId;
_storeParentPointer();
}
const blockstore::Key &key() const override {
return _baseBlob->key();
const blockstore::BlockId &blockId() const override {
return _baseBlob->blockId();
}
uint64_t size() const override {
@ -97,12 +97,12 @@ namespace cryfs {
}
#ifndef CRYFS_NO_COMPATIBILITY
static void migrate(blobstore::Blob *blob, const blockstore::Key &parentKey);
static void migrate(blobstore::Blob *blob, const blockstore::BlockId &parentId);
#endif
private:
static constexpr uint16_t FORMAT_VERSION_HEADER = 1;
static constexpr unsigned int HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::Key::BINARY_LENGTH;
static constexpr unsigned int HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::BlockId::BINARY_LENGTH;
static void _checkHeader(const blobstore::Blob &blob) {
uint16_t actualFormatVersion = getFormatVersionHeader(blob);
@ -118,18 +118,18 @@ namespace cryfs {
}
void _loadParentPointer() {
auto idData = cpputils::FixedSizeData<blockstore::Key::BINARY_LENGTH>::Null();
_baseBlob->read(idData.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
_parentPointer = blockstore::Key(idData);
auto idData = cpputils::FixedSizeData<blockstore::BlockId::BINARY_LENGTH>::Null();
_baseBlob->read(idData.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::BlockId::BINARY_LENGTH);
_parentPointer = blockstore::BlockId(idData);
}
void _storeParentPointer() {
_baseBlob->write(_parentPointer.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
_baseBlob->write(_parentPointer.data().data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::BlockId::BINARY_LENGTH);
}
cpputils::unique_ref<blobstore::Blob> _baseBlob;
blockstore::Key _parentPointer;
blockstore::BlockId _parentPointer;
DISALLOW_COPY_AND_ASSIGN(FsBlobView);
};

View File

@ -1,6 +1,6 @@
#include "SymlinkBlob.h"
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <cassert>
using std::string;
@ -18,7 +18,7 @@ SymlinkBlob::SymlinkBlob(unique_ref<Blob> blob)
ASSERT(baseBlob().blobType() == FsBlobView::BlobType::SYMLINK, "Loaded blob is not a symlink");
}
unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, const bf::path &target, const blockstore::Key &parent) {
unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, const bf::path &target, const blockstore::BlockId &parent) {
InitializeBlob(blob.get(), FsBlobView::BlobType::SYMLINK, parent);
FsBlobView symlinkBlobView(std::move(blob));
string targetStr = target.native();

View File

@ -11,7 +11,7 @@ namespace cryfs {
class SymlinkBlob final: public FsBlob {
public:
static cpputils::unique_ref<SymlinkBlob> InitializeSymlink(cpputils::unique_ref<blobstore::Blob> blob,
const boost::filesystem::path &target, const blockstore::Key &parent);
const boost::filesystem::path &target, const blockstore::BlockId &parent);
SymlinkBlob(cpputils::unique_ref<blobstore::Blob> blob);

View File

@ -2,7 +2,7 @@
using std::vector;
using std::string;
using blockstore::Key;
using blockstore::BlockId;
namespace cryfs {
namespace fsblobstore {
@ -23,7 +23,7 @@ namespace cryfs {
offset += _serializeTimeValue(dest + offset, _lastModificationTime);
offset += _serializeTimeValue(dest + offset, _lastMetadataChangeTime);
offset += _serializeString(dest + offset, _name);
offset += _serializeKey(dest + offset, _key);
offset += _serializeBlockId(dest + offset, _blockId);
ASSERT(offset == serializedSize(), "Didn't write correct number of elements");
}
@ -36,9 +36,9 @@ namespace cryfs {
timespec lastModificationTime = _deserializeTimeValue(&pos);
timespec lastMetadataChangeTime = _deserializeTimeValue(&pos);
string name = _deserializeString(&pos);
Key key = _deserializeKey(&pos);
BlockId blockId = _deserializeBlockId(&pos);
result->emplace_back(type, name, key, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime);
result->emplace_back(type, name, blockId, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime);
return pos;
}
@ -99,20 +99,20 @@ namespace cryfs {
return value;
}
unsigned int DirEntry::_serializeKey(uint8_t *dest, const Key &key) {
key.ToBinary(dest);
return key.BINARY_LENGTH;
unsigned int DirEntry::_serializeBlockId(uint8_t *dest, const BlockId &blockId) {
blockId.ToBinary(dest);
return blockId.BINARY_LENGTH;
}
Key DirEntry::_deserializeKey(const char **pos) {
Key key = Key::FromBinary(*pos);
*pos += Key::BINARY_LENGTH;
return key;
BlockId DirEntry::_deserializeBlockId(const char **pos) {
BlockId blockId = BlockId::FromBinary(*pos);
*pos += BlockId::BINARY_LENGTH;
return blockId;
}
size_t DirEntry::serializedSize() const {
return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (
_name.size() + 1) + _key.BINARY_LENGTH;
_name.size() + 1) + _blockId.BINARY_LENGTH;
}
}
}

View File

@ -2,7 +2,7 @@
#ifndef MESSMER_CRYFS_FILESYSTEM_FSBLOBSTORE_UTILS_DIRENTRY_H
#define MESSMER_CRYFS_FILESYSTEM_FSBLOBSTORE_UTILS_DIRENTRY_H
#include <blockstore/utils/Key.h>
#include <blockstore/utils/BlockId.h>
#include <fspp/fs_interface/Dir.h>
#include <cpp-utils/system/time.h>
#include <sys/stat.h>
@ -12,7 +12,7 @@ namespace cryfs {
class DirEntry final {
public:
DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::Key &key, mode_t mode,
DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::BlockId &blockId, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
timespec lastMetadataChangeTime);
@ -26,7 +26,7 @@ namespace cryfs {
const std::string &name() const;
void setName(const std::string &value);
const blockstore::Key &key() const;
const blockstore::BlockId &blockId() const;
mode_t mode() const;
void setMode(mode_t value);
@ -51,18 +51,18 @@ namespace cryfs {
static unsigned int _serializeUint8(uint8_t *dest, uint8_t value);
static unsigned int _serializeUint32(uint8_t *dest, uint32_t value);
static unsigned int _serializeString(uint8_t *dest, const std::string &value);
static unsigned int _serializeKey(uint8_t *dest, const blockstore::Key &value);
static unsigned int _serializeBlockId(uint8_t *dest, const blockstore::BlockId &value);
static timespec _deserializeTimeValue(const char **pos);
static uint8_t _deserializeUint8(const char **pos);
static uint32_t _deserializeUint32(const char **pos);
static std::string _deserializeString(const char **pos);
static blockstore::Key _deserializeKey(const char **pos);
static blockstore::BlockId _deserializeBlockId(const char **pos);
void _updateLastMetadataChangeTime();
fspp::Dir::EntryType _type;
std::string _name;
blockstore::Key _key;
blockstore::BlockId _blockId;
mode_t _mode;
uid_t _uid;
gid_t _gid;
@ -71,10 +71,10 @@ namespace cryfs {
timespec _lastMetadataChangeTime;
};
inline DirEntry::DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::Key &key, mode_t mode,
inline DirEntry::DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::BlockId &blockId, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
timespec lastMetadataChangeTime)
: _type(type), _name(name), _key(key), _mode(mode), _uid(uid), _gid(gid), _lastAccessTime(lastAccessTime),
: _type(type), _name(name), _blockId(blockId), _mode(mode), _uid(uid), _gid(gid), _lastAccessTime(lastAccessTime),
_lastModificationTime(lastModificationTime), _lastMetadataChangeTime(lastMetadataChangeTime) {
switch (_type) {
case fspp::Dir::EntryType::FILE:
@ -100,8 +100,8 @@ namespace cryfs {
return _name;
}
inline const blockstore::Key &DirEntry::key() const {
return _key;
inline const blockstore::BlockId &DirEntry::blockId() const {
return _blockId;
}
inline mode_t DirEntry::mode() const {

View File

@ -8,7 +8,7 @@
using cpputils::Data;
using std::string;
using std::vector;
using blockstore::Key;
using blockstore::BlockId;
namespace cryfs {
namespace fsblobstore {
@ -20,7 +20,7 @@ Data DirEntryList::serialize() const {
Data serialized(_serializedSize());
unsigned int offset = 0;
for (auto iter = _entries.begin(); iter != _entries.end(); ++iter) {
ASSERT(iter == _entries.begin() || std::less<Key>()((iter-1)->key(), iter->key()), "Invariant hurt: Directory entries should be ordered by key and not have duplicate keys.");
ASSERT(iter == _entries.begin() || std::less<BlockId>()((iter-1)->blockId(), iter->blockId()), "Invariant hurt: Directory entries should be ordered by blockId and not have duplicate blockIds.");
iter->serialize(static_cast<uint8_t*>(serialized.dataOffset(offset)));
offset += iter->serializedSize();
}
@ -40,7 +40,7 @@ void DirEntryList::deserializeFrom(const void *data, uint64_t size) {
const char *pos = static_cast<const char*>(data);
while (pos < static_cast<const char*>(data) + size) {
pos = DirEntry::deserializeAndAddToVector(pos, &_entries);
ASSERT(_entries.size() == 1 || std::less<Key>()(_entries[_entries.size()-2].key(), _entries[_entries.size()-1].key()), "Invariant hurt: Directory entries should be ordered by key and not have duplicate keys.");
ASSERT(_entries.size() == 1 || std::less<BlockId>()(_entries[_entries.size()-2].blockId(), _entries[_entries.size()-1].blockId()), "Invariant hurt: Directory entries should be ordered by blockId and not have duplicate blockIds.");
}
}
@ -48,41 +48,41 @@ bool DirEntryList::_hasChild(const string &name) const {
return _entries.end() != _findByName(name);
}
void DirEntryList::add(const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode,
void DirEntryList::add(const string &name, const BlockId &blobId, fspp::Dir::EntryType entryType, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
if (_hasChild(name)) {
throw fspp::fuse::FuseErrnoException(EEXIST);
}
_add(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_add(name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
}
void DirEntryList::_add(const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode,
void DirEntryList::_add(const string &name, const BlockId &blobId, fspp::Dir::EntryType entryType, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
auto insert_pos = _findUpperBound(blobKey);
_entries.emplace(insert_pos, entryType, name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime, cpputils::time::now());
auto insert_pos = _findUpperBound(blobId);
_entries.emplace(insert_pos, entryType, name, blobId, mode, uid, gid, lastAccessTime, lastModificationTime, cpputils::time::now());
}
void DirEntryList::addOrOverwrite(const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode,
void DirEntryList::addOrOverwrite(const string &name, const BlockId &blobId, fspp::Dir::EntryType entryType, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
std::function<void (const blockstore::Key &key)> onOverwritten) {
std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
auto found = _findByName(name);
if (found != _entries.end()) {
onOverwritten(found->key());
_overwrite(found, name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
onOverwritten(found->blockId());
_overwrite(found, name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
} else {
_add(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_add(name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
}
}
void DirEntryList::rename(const blockstore::Key &key, const std::string &name, std::function<void (const blockstore::Key &key)> onOverwritten) {
void DirEntryList::rename(const blockstore::BlockId &blockId, const std::string &name, std::function<void (const blockstore::BlockId &blockId)> onOverwritten) {
auto foundSameName = _findByName(name);
if (foundSameName != _entries.end() && foundSameName->key() != key) {
_checkAllowedOverwrite(foundSameName->type(), _findByKey(key)->type());
onOverwritten(foundSameName->key());
if (foundSameName != _entries.end() && foundSameName->blockId() != blockId) {
_checkAllowedOverwrite(foundSameName->type(), _findById(blockId)->type());
onOverwritten(foundSameName->blockId());
_entries.erase(foundSameName);
}
_findByKey(key)->setName(name);
_findById(blockId)->setName(name);
}
void DirEntryList::_checkAllowedOverwrite(fspp::Dir::EntryType oldType, fspp::Dir::EntryType newType) {
@ -98,13 +98,13 @@ void DirEntryList::_checkAllowedOverwrite(fspp::Dir::EntryType oldType, fspp::Di
}
}
void DirEntryList::_overwrite(vector<DirEntry>::iterator entry, const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode,
void DirEntryList::_overwrite(vector<DirEntry>::iterator entry, const string &name, const BlockId &blobId, fspp::Dir::EntryType entryType, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
_checkAllowedOverwrite(entry->type(), entryType);
// The new entry has possibly a different key, so it has to be in a different list position (list is ordered by keys).
// The new entry has possibly a different blockId, so it has to be in a different list position (list is ordered by blockIds).
// That's why we remove-and-add instead of just modifying the existing entry.
_entries.erase(entry);
_add(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_add(name, blobId, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
}
boost::optional<const DirEntry&> DirEntryList::get(const string &name) const {
@ -115,8 +115,8 @@ boost::optional<const DirEntry&> DirEntryList::get(const string &name) const {
return *found;
}
boost::optional<const DirEntry&> DirEntryList::get(const Key &key) const {
auto found = _findByKey(key);
boost::optional<const DirEntry&> DirEntryList::get(const BlockId &blockId) const {
auto found = _findById(blockId);
if (found == _entries.end()) {
return boost::none;
}
@ -131,10 +131,10 @@ void DirEntryList::remove(const string &name) {
_entries.erase(found);
}
void DirEntryList::remove(const Key &key) {
auto lowerBound = _findLowerBound(key);
auto upperBound = std::find_if(lowerBound, _entries.end(), [&key] (const DirEntry &entry) {
return entry.key() != key;
void DirEntryList::remove(const BlockId &blockId) {
auto lowerBound = _findLowerBound(blockId);
auto upperBound = std::find_if(lowerBound, _entries.end(), [&blockId] (const DirEntry &entry) {
return entry.blockId() != blockId;
});
_entries.erase(lowerBound, upperBound);
}
@ -149,27 +149,27 @@ vector<DirEntry>::const_iterator DirEntryList::_findByName(const string &name) c
return const_cast<DirEntryList*>(this)->_findByName(name);
}
vector<DirEntry>::iterator DirEntryList::_findByKey(const Key &key) {
auto found = _findLowerBound(key);
if (found == _entries.end() || found->key() != key) {
vector<DirEntry>::iterator DirEntryList::_findById(const BlockId &blockId) {
auto found = _findLowerBound(blockId);
if (found == _entries.end() || found->blockId() != blockId) {
throw fspp::fuse::FuseErrnoException(ENOENT);
}
return found;
}
vector<DirEntry>::iterator DirEntryList::_findLowerBound(const Key &key) {
return _findFirst(key, [&key] (const DirEntry &entry) {
return !std::less<Key>()(entry.key(), key);
vector<DirEntry>::iterator DirEntryList::_findLowerBound(const BlockId &blockId) {
return _findFirst(blockId, [&blockId] (const DirEntry &entry) {
return !std::less<BlockId>()(entry.blockId(), blockId);
});
}
vector<DirEntry>::iterator DirEntryList::_findUpperBound(const Key &key) {
return _findFirst(key, [&key] (const DirEntry &entry) {
return std::less<Key>()(key, entry.key());
vector<DirEntry>::iterator DirEntryList::_findUpperBound(const BlockId &blockId) {
return _findFirst(blockId, [&blockId] (const DirEntry &entry) {
return std::less<BlockId>()(blockId, entry.blockId());
});
}
vector<DirEntry>::iterator DirEntryList::_findFirst(const Key &hint, std::function<bool (const DirEntry&)> pred) {
vector<DirEntry>::iterator DirEntryList::_findFirst(const BlockId &hint, std::function<bool (const DirEntry&)> pred) {
//TODO Factor out a datastructure that keeps a sorted std::vector and allows these _findLowerBound()/_findUpperBound operations using this hinted linear search
if (_entries.size() == 0) {
return _entries.end();
@ -186,8 +186,8 @@ vector<DirEntry>::iterator DirEntryList::_findFirst(const Key &hint, std::functi
return iter;
}
vector<DirEntry>::const_iterator DirEntryList::_findByKey(const Key &key) const {
return const_cast<DirEntryList*>(this)->_findByKey(key);
vector<DirEntry>::const_iterator DirEntryList::_findById(const BlockId &blockId) const {
return const_cast<DirEntryList*>(this)->_findById(blockId);
}
size_t DirEntryList::size() const {
@ -202,14 +202,14 @@ DirEntryList::const_iterator DirEntryList::end() const {
return _entries.end();
}
void DirEntryList::setMode(const Key &key, mode_t mode) {
auto found = _findByKey(key);
void DirEntryList::setMode(const BlockId &blockId, mode_t mode) {
auto found = _findById(blockId);
ASSERT ((S_ISREG(mode) && S_ISREG(found->mode())) || (S_ISDIR(mode) && S_ISDIR(found->mode())) || (S_ISLNK(mode)), "Unknown mode in entry");
found->setMode(mode);
}
bool DirEntryList::setUidGid(const Key &key, uid_t uid, gid_t gid) {
auto found = _findByKey(key);
bool DirEntryList::setUidGid(const BlockId &blockId, uid_t uid, gid_t gid) {
auto found = _findById(blockId);
bool changed = false;
if (uid != (uid_t)-1) {
found->setUid(uid);
@ -222,15 +222,15 @@ bool DirEntryList::setUidGid(const Key &key, uid_t uid, gid_t gid) {
return changed;
}
void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime) {
auto found = _findByKey(key);
void DirEntryList::setAccessTimes(const blockstore::BlockId &blockId, timespec lastAccessTime, timespec lastModificationTime) {
auto found = _findById(blockId);
found->setLastAccessTime(lastAccessTime);
found->setLastModificationTime(lastModificationTime);
}
bool DirEntryList::updateAccessTimestampForChild(const blockstore::Key &key, TimestampUpdateBehavior timestampUpdateBehavior) {
bool DirEntryList::updateAccessTimestampForChild(const blockstore::BlockId &blockId, TimestampUpdateBehavior timestampUpdateBehavior) {
ASSERT(timestampUpdateBehavior == TimestampUpdateBehavior::RELATIME, "Currently only relatime supported");
auto found = _findByKey(key);
auto found = _findById(blockId);
const timespec lastAccessTime = found->lastAccessTime();
const timespec lastModificationTime = found->lastModificationTime();
const timespec now = cpputils::time::now();
@ -246,8 +246,8 @@ bool DirEntryList::updateAccessTimestampForChild(const blockstore::Key &key, Tim
return changed;
}
void DirEntryList::updateModificationTimestampForChild(const blockstore::Key &key) {
auto found = _findByKey(key);
void DirEntryList::updateModificationTimestampForChild(const blockstore::BlockId &blockId) {
auto found = _findById(blockId);
found->setLastModificationTime(cpputils::time::now());
}

Some files were not shown because too many files have changed in this diff Show More