Use the new assert that doesn't crash the program in a release build
This commit is contained in:
parent
e64255a16e
commit
106f18b496
@ -4,6 +4,7 @@
|
||||
#include "datanodestore/DataLeafNode.h"
|
||||
#include "utils/Math.h"
|
||||
#include <cmath>
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using std::function;
|
||||
using cpputils::unique_ref;
|
||||
@ -49,9 +50,9 @@ void BlobOnBlocks::traverseLeaves(uint64_t beginByte, uint64_t sizeBytes, functi
|
||||
}
|
||||
|
||||
void BlobOnBlocks::read(void *target, uint64_t offset, uint64_t count) const {
|
||||
assert(offset <= _datatree->numStoredBytes() && offset + count <= size());
|
||||
ASSERT(offset <= _datatree->numStoredBytes() && offset + count <= size(), "BlobOnBlocks::read() read outside blob. Use BlobOnBlocks::tryRead() if this should be allowed.");
|
||||
uint64_t read = tryRead(target, offset, count);
|
||||
assert(read == count);
|
||||
ASSERT(read == count, "BlobOnBlocks::read() couldn't read all requested bytes. Use BlobOnBlocks::tryRead() if this should be allowed.");
|
||||
}
|
||||
|
||||
uint64_t BlobOnBlocks::tryRead(void *target, uint64_t offset, uint64_t count) const {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "BlobStoreOnBlocks.h"
|
||||
#include "BlobOnBlocks.h"
|
||||
#include <messmer/cpp-utils/pointer/cast.h>
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
@ -47,7 +48,7 @@ optional<unique_ref<Blob>> BlobStoreOnBlocks::load(const Key &key) {
|
||||
|
||||
void BlobStoreOnBlocks::remove(unique_ref<Blob> blob) {
|
||||
auto _blob = dynamic_pointer_move<BlobOnBlocks>(blob);
|
||||
assert(_blob != none);
|
||||
ASSERT(_blob != none, "Passed Blob in BlobStoreOnBlocks::remove() is not a BlobOnBlocks.");
|
||||
_dataTreeStore->remove((*_blob)->releaseTree());
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "DataInnerNode.h"
|
||||
#include "DataNodeStore.h"
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using blockstore::Block;
|
||||
using cpputils::Data;
|
||||
@ -13,7 +14,7 @@ namespace datanodestore {
|
||||
|
||||
DataInnerNode::DataInnerNode(DataNodeView view)
|
||||
: DataNode(std::move(view)) {
|
||||
assert(depth() > 0);
|
||||
ASSERT(depth() > 0, "Inner node can't have depth 0. Is this a leaf maybe?");
|
||||
}
|
||||
|
||||
DataInnerNode::~DataInnerNode() {
|
||||
@ -61,19 +62,19 @@ DataInnerNode::ChildEntry *DataInnerNode::getChild(unsigned int index) {
|
||||
}
|
||||
|
||||
const DataInnerNode::ChildEntry *DataInnerNode::getChild(unsigned int index) const {
|
||||
assert(index < numChildren());
|
||||
ASSERT(index < numChildren(), "Accessing child out of range");
|
||||
return ChildrenBegin()+index;
|
||||
}
|
||||
|
||||
void DataInnerNode::addChild(const DataNode &child) {
|
||||
assert(numChildren() < maxStoreableChildren());
|
||||
assert(child.depth() == depth()-1);
|
||||
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());
|
||||
}
|
||||
|
||||
void DataInnerNode::removeLastChild() {
|
||||
assert(node().Size() > 1);
|
||||
ASSERT(node().Size() > 1, "There is no child to remove");
|
||||
node().setSize(node().Size()-1);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "DataLeafNode.h"
|
||||
#include "DataInnerNode.h"
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using blockstore::Block;
|
||||
using cpputils::Data;
|
||||
@ -13,8 +14,8 @@ namespace datanodestore {
|
||||
|
||||
DataLeafNode::DataLeafNode(DataNodeView view)
|
||||
: DataNode(std::move(view)) {
|
||||
assert(node().Depth() == 0);
|
||||
assert(numBytes() <= maxStoreableBytes());
|
||||
ASSERT(node().Depth() == 0, "Leaf node must have depth 0. Is it an inner node instead?");
|
||||
ASSERT(numBytes() <= maxStoreableBytes(), "Leaf says it stores more bytes than it has space for");
|
||||
}
|
||||
|
||||
DataLeafNode::~DataLeafNode() {
|
||||
@ -29,12 +30,12 @@ unique_ref<DataLeafNode> DataLeafNode::InitializeNewNode(unique_ref<Block> block
|
||||
}
|
||||
|
||||
void DataLeafNode::read(void *target, uint64_t offset, uint64_t size) const {
|
||||
assert(offset <= node().Size() && offset + size <= node().Size()); // Also check offset, because the addition could lead to overflows
|
||||
ASSERT(offset <= node().Size() && offset + size <= node().Size(), "Read out of valid area"); // Also check offset, because the addition could lead to overflows
|
||||
std::memcpy(target, (uint8_t*)node().data() + offset, size);
|
||||
}
|
||||
|
||||
void DataLeafNode::write(const void *source, uint64_t offset, uint64_t size) {
|
||||
assert(offset <= node().Size() && offset + size <= node().Size()); // Also check offset, because the addition could lead to overflows
|
||||
ASSERT(offset <= node().Size() && offset + size <= node().Size(), "Write out of valid area"); // Also check offset, because the addition could lead to overflows
|
||||
node().write(source, offset, size);
|
||||
}
|
||||
|
||||
@ -43,7 +44,7 @@ uint32_t DataLeafNode::numBytes() const {
|
||||
}
|
||||
|
||||
void DataLeafNode::resize(uint32_t new_size) {
|
||||
assert(new_size <= maxStoreableBytes());
|
||||
ASSERT(new_size <= maxStoreableBytes(), "Trying to resize to a size larger than the maximal size");
|
||||
uint32_t old_size = node().Size();
|
||||
if (new_size < old_size) {
|
||||
fillDataWithZeroesFromTo(new_size, old_size);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "messmer/blockstore/interface/BlockStore.h"
|
||||
#include "messmer/blockstore/interface/Block.h"
|
||||
#include "messmer/blockstore/utils/BlockStoreUtils.h"
|
||||
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using blockstore::BlockStore;
|
||||
using blockstore::Block;
|
||||
@ -28,7 +28,7 @@ DataNodeStore::~DataNodeStore() {
|
||||
}
|
||||
|
||||
unique_ref<DataNode> DataNodeStore::load(unique_ref<Block> block) {
|
||||
assert(block->size() == _layout.blocksizeBytes());
|
||||
ASSERT(block->size() == _layout.blocksizeBytes(), "Loading block of wrong size");
|
||||
DataNodeView node(std::move(block));
|
||||
|
||||
if (node.Depth() == 0) {
|
||||
@ -41,7 +41,7 @@ unique_ref<DataNode> DataNodeStore::load(unique_ref<Block> block) {
|
||||
}
|
||||
|
||||
unique_ref<DataInnerNode> DataNodeStore::createNewInnerNode(const DataNode &first_child) {
|
||||
assert(first_child.node().layout().blocksizeBytes() == _layout.blocksizeBytes()); // This might be violated if source is from a different DataNodeStore
|
||||
ASSERT(first_child.node().layout().blocksizeBytes() == _layout.blocksizeBytes(), "Source node has wrong layout. Is it from the same DataNodeStore?");
|
||||
//TODO Initialize block and then create it in the blockstore - this is more efficient than creating it and then writing to it
|
||||
auto block = _blockstore->create(Data(_layout.blocksizeBytes()).FillWithZeroes());
|
||||
return DataInnerNode::InitializeNewNode(std::move(block), first_child);
|
||||
@ -63,14 +63,14 @@ optional<unique_ref<DataNode>> DataNodeStore::load(const Key &key) {
|
||||
}
|
||||
|
||||
unique_ref<DataNode> DataNodeStore::createNewNodeAsCopyFrom(const DataNode &source) {
|
||||
assert(source.node().layout().blocksizeBytes() == _layout.blocksizeBytes()); // This might be violated if source is from a different DataNodeStore
|
||||
ASSERT(source.node().layout().blocksizeBytes() == _layout.blocksizeBytes(), "Source node has wrong layout. Is it from the same DataNodeStore?");
|
||||
auto newBlock = blockstore::utils::copyToNewBlock(_blockstore.get(), source.node().block());
|
||||
return load(std::move(newBlock));
|
||||
}
|
||||
|
||||
unique_ref<DataNode> DataNodeStore::overwriteNodeWith(unique_ref<DataNode> target, const DataNode &source) {
|
||||
assert(target->node().layout().blocksizeBytes() == _layout.blocksizeBytes());
|
||||
assert(source.node().layout().blocksizeBytes() == _layout.blocksizeBytes());
|
||||
ASSERT(target->node().layout().blocksizeBytes() == _layout.blocksizeBytes(), "Target node has wrong layout. Is it from the same DataNodeStore?");
|
||||
ASSERT(source.node().layout().blocksizeBytes() == _layout.blocksizeBytes(), "Source node has wrong layout. Is it from the same DataNodeStore?");
|
||||
Key key = target->key();
|
||||
{
|
||||
auto targetBlock = target->node().releaseBlock();
|
||||
@ -78,7 +78,7 @@ unique_ref<DataNode> DataNodeStore::overwriteNodeWith(unique_ref<DataNode> targe
|
||||
blockstore::utils::copyTo(targetBlock.get(), source.node().block());
|
||||
}
|
||||
auto loaded = load(key);
|
||||
assert(loaded != none);
|
||||
ASSERT(loaded != none, "Couldn't load the target node after overwriting it");
|
||||
return std::move(*loaded);
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ void DataNodeStore::removeSubtree(unique_ref<DataNode> node) {
|
||||
if (inner != nullptr) {
|
||||
for (uint32_t i = 0; i < inner->numChildren(); ++i) {
|
||||
auto child = load(inner->getChild(i)->key());
|
||||
assert(child != none);
|
||||
ASSERT(child != none, "Couldn't load child node");
|
||||
removeSubtree(std::move(*child));
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "messmer/cpp-utils/pointer/cast.h"
|
||||
#include "messmer/cpp-utils/pointer/optional_ownership_ptr.h"
|
||||
#include <cmath>
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using blockstore::Key;
|
||||
using blobstore::onblocks::datanodestore::DataNodeStore;
|
||||
@ -45,7 +46,7 @@ DataTree::~DataTree() {
|
||||
|
||||
void DataTree::removeLastDataLeaf() {
|
||||
auto deletePosOrNull = algorithms::GetLowestRightBorderNodeWithMoreThanOneChildOrNull(_nodeStore, _rootNode.get());
|
||||
assert(deletePosOrNull.get() != nullptr); //TODO Correct exception (tree has only one leaf, can't shrink it)
|
||||
ASSERT(deletePosOrNull.get() != nullptr, "Tree has only one leaf, can't shrink it.");
|
||||
|
||||
deleteLastChildSubtree(deletePosOrNull.get());
|
||||
|
||||
@ -54,10 +55,10 @@ void DataTree::removeLastDataLeaf() {
|
||||
|
||||
void DataTree::ifRootHasOnlyOneChildReplaceRootWithItsChild() {
|
||||
DataInnerNode *rootNode = dynamic_cast<DataInnerNode*>(_rootNode.get());
|
||||
assert(rootNode != nullptr);
|
||||
ASSERT(rootNode != nullptr, "RootNode is not an inner node");
|
||||
if (rootNode->numChildren() == 1) {
|
||||
auto child = _nodeStore->load(rootNode->getChild(0)->key());
|
||||
assert(child != none);
|
||||
ASSERT(child != none, "Couldn't load first child of root node");
|
||||
_rootNode = _nodeStore->overwriteNodeWith(std::move(_rootNode), **child);
|
||||
_nodeStore->remove(std::move(*child));
|
||||
}
|
||||
@ -65,7 +66,7 @@ void DataTree::ifRootHasOnlyOneChildReplaceRootWithItsChild() {
|
||||
|
||||
void DataTree::deleteLastChildSubtree(DataInnerNode *node) {
|
||||
auto lastChild = _nodeStore->load(node->LastChild()->key());
|
||||
assert(lastChild != none);
|
||||
ASSERT(lastChild != none, "Couldn't load last child");
|
||||
_nodeStore->removeSubtree(std::move(*lastChild));
|
||||
node->removeLastChild();
|
||||
}
|
||||
@ -105,7 +106,7 @@ unique_ref<DataNode> DataTree::createChainOfInnerNodes(unsigned int num, unique_
|
||||
}
|
||||
|
||||
DataInnerNode* DataTree::increaseTreeDepth(unsigned int levels) {
|
||||
assert(levels >= 1);
|
||||
ASSERT(levels >= 1, "Parameter out of bounds: tried to increase tree depth by zero.");
|
||||
auto copyOfOldRoot = _nodeStore->createNewNodeAsCopyFrom(*_rootNode);
|
||||
auto chain = createChainOfInnerNodes(levels-1, copyOfOldRoot.get());
|
||||
auto newRootNode = DataNode::convertToNewInnerNode(std::move(_rootNode), *chain);
|
||||
@ -146,7 +147,7 @@ uint32_t DataTree::_numLeaves(const DataNode &node) const {
|
||||
const DataInnerNode &inner = dynamic_cast<const DataInnerNode&>(node);
|
||||
uint64_t numLeavesInLeftChildren = (inner.numChildren()-1) * leavesPerFullChild(inner);
|
||||
auto lastChild = _nodeStore->load(inner.LastChild()->key());
|
||||
assert(lastChild != none);
|
||||
ASSERT(lastChild != none, "Couldn't load last child");
|
||||
uint64_t numLeavesInRightChild = _numLeaves(**lastChild);
|
||||
|
||||
return numLeavesInLeftChildren + numLeavesInRightChild;
|
||||
@ -154,7 +155,7 @@ uint32_t DataTree::_numLeaves(const DataNode &node) const {
|
||||
|
||||
void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function<void (DataLeafNode*, uint32_t)> func) {
|
||||
unique_lock<shared_mutex> lock(_mutex); //TODO Only lock when resizing
|
||||
assert(beginIndex <= endIndex);
|
||||
ASSERT(beginIndex <= endIndex, "Invalid parameters");
|
||||
|
||||
uint8_t neededTreeDepth = utils::ceilLog(_nodeStore->layout().maxChildrenPerInnerNode(), endIndex);
|
||||
uint32_t numLeaves = this->numLeaves();
|
||||
@ -192,7 +193,7 @@ void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function<v
|
||||
void DataTree::_traverseLeaves(DataNode *root, uint32_t leafOffset, uint32_t beginIndex, uint32_t endIndex, function<void (DataLeafNode*, uint32_t)> func) {
|
||||
DataLeafNode *leaf = dynamic_cast<DataLeafNode*>(root);
|
||||
if (leaf != nullptr) {
|
||||
assert(beginIndex <= 1 && endIndex <= 1);
|
||||
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.");
|
||||
if (beginIndex == 0 && endIndex == 1) {
|
||||
func(leaf, leafOffset);
|
||||
}
|
||||
@ -219,13 +220,13 @@ vector<unique_ref<DataNode>> DataTree::getOrCreateChildren(DataInnerNode *node,
|
||||
children.reserve(end-begin);
|
||||
for (uint32_t childIndex = begin; childIndex < std::min(node->numChildren(), end); ++childIndex) {
|
||||
auto child = _nodeStore->load(node->getChild(childIndex)->key());
|
||||
assert(child != none);
|
||||
ASSERT(child != none, "Couldn't load child node");
|
||||
children.emplace_back(std::move(*child));
|
||||
}
|
||||
for (uint32_t childIndex = node->numChildren(); childIndex < end; ++childIndex) {
|
||||
children.emplace_back(addChildTo(node));
|
||||
}
|
||||
assert(children.size() == end-begin);
|
||||
ASSERT(children.size() == end-begin, "Number of children in the result is wrong");
|
||||
return children;
|
||||
}
|
||||
|
||||
@ -259,7 +260,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());
|
||||
assert(lastChild != none);
|
||||
ASSERT(lastChild != none, "Couldn't load last child");
|
||||
uint64_t numBytesInRightChild = _numStoredBytes(**lastChild);
|
||||
|
||||
return numBytesInLeftChildren + numBytesInRightChild;
|
||||
@ -272,7 +273,7 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
|
||||
//TODO Faster implementation possible (no addDataLeaf()/removeLastDataLeaf() in a loop, but directly resizing)
|
||||
LastLeaf(_rootNode.get())->resize(_nodeStore->layout().maxBytesPerLeaf());
|
||||
uint64_t currentNumBytes = _numStoredBytes();
|
||||
assert(currentNumBytes % _nodeStore->layout().maxBytesPerLeaf() == 0);
|
||||
ASSERT(currentNumBytes % _nodeStore->layout().maxBytesPerLeaf() == 0, "The last leaf is not a max data leaf, although we just resized it to be one.");
|
||||
uint32_t currentNumLeaves = currentNumBytes / _nodeStore->layout().maxBytesPerLeaf();
|
||||
uint32_t newNumLeaves = std::max(1u, utils::ceilDivision(newNumBytes, _nodeStore->layout().maxBytesPerLeaf()));
|
||||
|
||||
@ -285,7 +286,7 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
|
||||
uint32_t newLastLeafSize = newNumBytes - (newNumLeaves-1)*_nodeStore->layout().maxBytesPerLeaf();
|
||||
LastLeaf(_rootNode.get())->resize(newLastLeafSize);
|
||||
}
|
||||
assert(newNumBytes == numStoredBytes());
|
||||
ASSERT(newNumBytes == numStoredBytes(), "We resized to the wrong number of bytes");
|
||||
}
|
||||
|
||||
optional_ownership_ptr<DataLeafNode> DataTree::LastLeaf(DataNode *root) {
|
||||
@ -296,7 +297,7 @@ optional_ownership_ptr<DataLeafNode> DataTree::LastLeaf(DataNode *root) {
|
||||
|
||||
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root);
|
||||
auto lastChild = _nodeStore->load(inner->LastChild()->key());
|
||||
assert(lastChild != none);
|
||||
ASSERT(lastChild != none, "Couldn't load last child");
|
||||
return WithOwnership(LastLeaf(std::move(*lastChild)));
|
||||
}
|
||||
|
||||
@ -306,9 +307,9 @@ unique_ref<DataLeafNode> DataTree::LastLeaf(unique_ref<DataNode> root) {
|
||||
return std::move(*leaf);
|
||||
}
|
||||
auto inner = dynamic_pointer_move<DataInnerNode>(root);
|
||||
assert(inner != none);
|
||||
ASSERT(inner != none, "Root node is neither a leaf nor an inner node");
|
||||
auto child = _nodeStore->load((*inner)->LastChild()->key());
|
||||
assert(child != none);
|
||||
ASSERT(child != none, "Couldn't load last child");
|
||||
return LastLeaf(std::move(*child));
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "../../datanodestore/DataInnerNode.h"
|
||||
#include "../../datanodestore/DataNodeStore.h"
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
using std::function;
|
||||
using cpputils::optional_ownership_ptr;
|
||||
@ -24,7 +25,7 @@ namespace algorithms {
|
||||
optional<unique_ref<DataInnerNode>> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
|
||||
Key key = node.LastChild()->key();
|
||||
auto lastChild = nodeStore->load(key);
|
||||
assert(lastChild != none);
|
||||
ASSERT(lastChild != none, "Couldn't load last child");
|
||||
return dynamic_pointer_move<DataInnerNode>(*lastChild);
|
||||
}
|
||||
|
||||
@ -39,7 +40,7 @@ optional_ownership_ptr<DataInnerNode> GetLowestInnerRightBorderNodeWithCondition
|
||||
if (condition(*currentNode)) {
|
||||
result = std::move(currentNode);
|
||||
}
|
||||
assert(lastChild != none || static_cast<int>(i) == rootNode->depth()-1);
|
||||
ASSERT(lastChild != none || static_cast<int>(i) == rootNode->depth()-1, "Couldn't get last child as inner node but we're not deep enough yet for the last child to be a leaf");
|
||||
if (lastChild != none) {
|
||||
currentNode = cpputils::WithOwnership(std::move(*lastChild));
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ unique_ref<DataInnerNode> DataTreeTest::CreateInner(initializer_list<const DataN
|
||||
}
|
||||
|
||||
unique_ref<DataInnerNode> DataTreeTest::CreateInner(vector<const DataNode*> children) {
|
||||
assert(children.size() >= 1);
|
||||
ASSERT(children.size() >= 1, "An inner node must have at least one child");
|
||||
auto node = nodeStore->createNewInnerNode(**children.begin());
|
||||
for(auto child = children.begin()+1; child != children.end(); ++child) {
|
||||
node->addChild(**child);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <messmer/cpp-utils/macros.h>
|
||||
#include <messmer/cpp-utils/pointer/cast.h>
|
||||
#include "LeafDataFixture.h"
|
||||
#include <messmer/cpp-utils/assert/assert.h>
|
||||
|
||||
//TODO Rename, since we now allow any number of levels
|
||||
// A data fixture containing data for a two-level tree (one inner node with leaf children).
|
||||
@ -70,7 +71,8 @@ private:
|
||||
case SizePolicy::Unchanged:
|
||||
return leaf->numBytes();
|
||||
default:
|
||||
assert(false);
|
||||
ASSERT(false, "Unknown size policy");
|
||||
abort(); // The assert above already aborts. This is just to prevent the style checker from complaining about exiting a non-void function
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user