Use the new assert that doesn't crash the program in a release build

This commit is contained in:
Sebastian Messmer 2015-07-22 13:42:44 +02:00
parent e64255a16e
commit 106f18b496
9 changed files with 49 additions and 41 deletions

View File

@ -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 {

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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));
}
}

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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);

View File

@ -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
}
}