Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't treat leaf as a node in the directory tree node, also simplify the reference #69

Merged
merged 6 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions src/directory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,12 @@ Directory::iterator Directory::begin() const {
while (!(current_block->get_object<MetadataBlockHeader>(0)->block_flags.value() &
MetadataBlockHeader::Flags::DIRECTORY_LEAF_TREE)) {
parents.push_back({std::move(current_block)});
parents.back().iterator = parents.back().node->begin();
parents.back().iterator = parents.back().node.begin();
assert(!parents.back().iterator.is_end());
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents.back().iterator).value));
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents.back().iterator).value()));
}
iterator::leaf_node_info leaf{std::move(current_block)};
leaf.iterator = leaf.node->begin();
assert(!leaf.iterator.is_end());
leaf.iterator = leaf.node.begin();
return {quota_, std::move(parents), std::move(leaf)};
}

Expand All @@ -77,12 +76,12 @@ Directory::iterator Directory::end() const {
while (!(current_block->get_object<MetadataBlockHeader>(0)->block_flags.value() &
MetadataBlockHeader::Flags::DIRECTORY_LEAF_TREE)) {
parents.push_back({std::move(current_block)});
parents.back().iterator = parents.back().node->end();
parents.back().iterator = parents.back().node.end();
assert(!parents.back().iterator.is_begin());
current_block = throw_if_error(quota_->LoadMetadataBlock((*--parents.back().iterator).value));
current_block = throw_if_error(quota_->LoadMetadataBlock((*--parents.back().iterator).value()));
}
iterator::leaf_node_info leaf{std::move(current_block)};
leaf.iterator = leaf.node->end();
leaf.iterator = leaf.node.end();
return {quota_, std::move(parents), std::move(leaf)};
}

Expand All @@ -94,12 +93,12 @@ Directory::iterator Directory::find(std::string_view key, bool exact_match) cons
while (!(current_block->get_object<MetadataBlockHeader>(0)->block_flags.value() &
MetadataBlockHeader::Flags::DIRECTORY_LEAF_TREE)) {
parents.push_back({std::move(current_block)});
parents.back().iterator = parents.back().node->find(key, /*exact_match=*/false);
parents.back().iterator = parents.back().node.find(key, /*exact_match=*/false);
assert(!parents.back().iterator.is_end());
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents.back().iterator).value));
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents.back().iterator).value()));
}
iterator::leaf_node_info leaf{std::move(current_block)};
leaf.iterator = leaf.node->find(key, exact_match);
leaf.iterator = leaf.node.find(key, exact_match);
return {quota_, std::move(parents), std::move(leaf)};
}

Expand All @@ -110,7 +109,7 @@ size_t Directory::CalcSizeOfDirectoryBlock(std::shared_ptr<Block> block) const {
} else {
DirectoryParentTree tree{std::move(block)};
return std::accumulate(tree.begin(), tree.end(), size_t{0}, [&](auto acc, const auto& node) {
return acc + CalcSizeOfDirectoryBlock(throw_if_error(quota_->LoadMetadataBlock(node.value)));
return acc + CalcSizeOfDirectoryBlock(throw_if_error(quota_->LoadMetadataBlock(node.value())));
});
}
};
29 changes: 10 additions & 19 deletions src/directory_iterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ DirectoryIterator::reference DirectoryIterator::operator*() const {
auto val = *leaf_.iterator;
// TODO: return key case sensitive?
// TODO: Maybe have an attributes iteration and a wrapper for WfsItem iteration (call it DirectoryAttributesIterator?)
return {val.key, WfsItem::Load(quota_, val.key, attributes())};
return {val.key(), WfsItem::Load(quota_, val.key(), attributes())};
}

DirectoryIterator& DirectoryIterator::operator++() {
Expand All @@ -34,20 +34,20 @@ DirectoryIterator& DirectoryIterator::operator++() {
// end
for (auto& parent : removed_parents) {
--parent.iterator;
removed_parents.push_front(std::move(parent));
parents_.push_front(std::move(parent));
}
return *this;
}
auto current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value));
auto current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value()));
while (!(current_block->get_object<MetadataBlockHeader>(0)->block_flags.value() &
MetadataBlockHeader::Flags::DIRECTORY_LEAF_TREE)) {
parents_.push_back({std::move(current_block)});
parents_.back().iterator = parents_.back().node->begin();
parents_.back().iterator = parents_.back().node.begin();
assert(!parents_.back().iterator.is_end());
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value));
current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value()));
}
leaf_ = {std::move(current_block)};
leaf_.iterator = leaf_.node->begin();
leaf_.iterator = leaf_.node.begin();
assert(!leaf_.iterator.is_end());
}
return *this;
Expand All @@ -56,28 +56,19 @@ DirectoryIterator& DirectoryIterator::operator++() {
DirectoryIterator& DirectoryIterator::operator--() {
assert(!is_begin());
if (leaf_.iterator.is_begin()) {
std::deque<parent_node_info> removed_parents;
while (!parents_.empty() && parents_.back().iterator.is_begin()) {
removed_parents.push_back(std::move(parents_.back()));
parents_.pop_back();
}
if (parents_.empty()) {
// begin
for (auto& parent : removed_parents) {
removed_parents.push_front(std::move(parent));
}
return *this;
}
auto current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value));
auto current_block = throw_if_error(quota_->LoadMetadataBlock((*parents_.back().iterator).value()));
while (!(current_block->get_object<MetadataBlockHeader>(0)->block_flags.value() &
MetadataBlockHeader::Flags::DIRECTORY_LEAF_TREE)) {
parents_.push_back({std::move(current_block)});
parents_.back().iterator = parents_.back().node->end();
parents_.back().iterator = parents_.back().node.end();
assert(!parents_.back().iterator.is_begin());
current_block = throw_if_error(quota_->LoadMetadataBlock((*--parents_.back().iterator).value));
current_block = throw_if_error(quota_->LoadMetadataBlock((*--parents_.back().iterator).value()));
}
leaf_ = {std::move(current_block)};
leaf_.iterator = leaf_.node->end();
leaf_.iterator = leaf_.node.end();
assert(!leaf_.iterator.is_begin());
}
--leaf_.iterator;
Expand Down
2 changes: 1 addition & 1 deletion src/directory_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class DirectoryIterator {
bool is_begin() const;
bool is_end() const { return leaf_.iterator.is_end(); }

Block::DataRef<Attributes> attributes() const { return {leaf_.node->block(), uint16_t{(*leaf_.iterator).value}}; }
Block::DataRef<Attributes> attributes() const { return {leaf_.node.block(), uint16_t{(*leaf_.iterator).value()}}; }

private:
std::shared_ptr<QuotaArea> quota_;
Expand Down
1 change: 1 addition & 0 deletions src/directory_leaf_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@

class DirectoryLeafTree : public DirectoryTree<dir_leaf_tree_value_type> {
public:
DirectoryLeafTree() = default;
DirectoryLeafTree(std::shared_ptr<Block> block) : DirectoryTree(std::move(block)) {}
};
1 change: 1 addition & 0 deletions src/directory_parent_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@

class DirectoryParentTree : public DirectoryTree<dir_parent_tree_value_type> {
public:
DirectoryParentTree() = default;
DirectoryParentTree(std::shared_ptr<Block> block) : DirectoryTree(std::move(block)) {}
};
109 changes: 58 additions & 51 deletions src/directory_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class DirectoryTree : public SubBlockAllocator<DirectoryTreeHeader> {

using node = DirectoryTreeNode<LeafValueType>;

DirectoryTree() = default;
DirectoryTree(std::shared_ptr<Block> block) : SubBlockAllocator<DirectoryTreeHeader>(std::move(block)) {}
virtual ~DirectoryTree() = default;

Expand All @@ -29,28 +30,34 @@ class DirectoryTree : public SubBlockAllocator<DirectoryTreeHeader> {

iterator begin() const {
if (size() == 0)
return {block().get(), {}};
std::deque<typename iterator::node_info> nodes;
do {
uint16_t node_offset = nodes.empty() ? extra_header()->root.value() : (*nodes.back().iterator).value;
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block().get(), node_offset)});
nodes.back().iterator = nodes.back().node->begin();
} while (!nodes.back().iterator.is_leaf_value());
return {block().get(), std::move(nodes)};
return {block().get(), {}, {}};
std::deque<typename iterator::parent_node_info> parents;
uint16_t node_offset = extra_header()->root.value();
while (true) {
decltype(iterator::parent_node_info::node) parent{
dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset)};
if (parent.has_leaf()) {
return {block().get(), std::move(parents), parent.leaf()};
}
parents.push_back({parent, parent.begin()});
node_offset = (*parents.back().iterator).value();
}
}

iterator end() const {
if (size() == 0)
return {block().get(), {}};
std::deque<typename iterator::node_info> nodes;
do {
uint16_t node_offset = nodes.empty() ? extra_header()->root.value() : (*nodes.back().iterator).value;
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block().get(), node_offset)});
nodes.back().iterator = nodes.back().node->end();
assert(!nodes.back().iterator.is_begin());
--nodes.back().iterator;
} while (!nodes.back().iterator.is_leaf_value());
++nodes.back().iterator;
return {block().get(), std::move(nodes)};
return {block().get(), {}, {}};
std::deque<typename iterator::parent_node_info> parents;
uint16_t node_offset = extra_header()->root.value();
while (true) {
parents.push_back({dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset)});
parents.back().iterator = parents.back().node.end();
if (parents.back().node.size() == 0) {
return {block().get(), std::move(parents), {}};
}
--parents.back().iterator;
node_offset = (*parents.back().iterator).value();
}
}

iterator middle() const {
Expand All @@ -64,30 +71,30 @@ class DirectoryTree : public SubBlockAllocator<DirectoryTreeHeader> {
iterator find(std::string_view key, bool exact_match = true) const {
if (size() == 0)
return end();
std::deque<typename iterator::node_info> nodes;
std::deque<typename iterator::parent_node_info> parents;
uint16_t node_offset = extra_header()->root.value();
auto current_key = key.begin();
while (true) {
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block().get(), node_offset)});
auto& node = nodes.back();
auto prefix = node.node->prefix();
decltype(iterator::parent_node_info::node) parent{
dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset)};
auto prefix = parent.prefix();
auto [key_it, prefix_it] = std::ranges::mismatch(std::ranges::subrange(current_key, key.end()), prefix);
if (key_it == key.end()) {
// Got to end of our key
if (prefix_it == prefix.end()) {
// Full match, check if there is a node
node.iterator = node.node->begin();
if (node.iterator.is_leaf_value()) {
if (parent.has_leaf()) {
// Found exact match!
return {block().get(), std::move(nodes)};
return {block().get(), std::move(parents), parent.leaf()};
}
}
} else if (prefix_it == prefix.end()) {
// We matched the prefix
node.iterator = node.node->find(*key_it, exact_match);
if (node.iterator != node.node->end() && (*node.iterator).key >= *key_it) {
auto iterator = parent.find(*key_it, exact_match);
if (iterator != parent.end() && (*iterator).key() >= *key_it) {
current_key = key_it + 1;
node_offset = (*node.iterator).value;
node_offset = (*iterator).value();
parents.push_back({parent, iterator});
continue;
}
}
Expand All @@ -96,23 +103,24 @@ class DirectoryTree : public SubBlockAllocator<DirectoryTreeHeader> {
if (prefix_it == prefix.end() || std::lexicographical_compare(key_it, key.end(), prefix_it, prefix.end())) {
// We are smaller than current prefix + smallest key, which mean that we overshoot, go back to last leaf by
// getting next leaf first.
while (node.iterator = node.node->begin(), !node.iterator.is_leaf_value()) {
node_offset = (*node.iterator).value;
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block().get(), node_offset)});
node = nodes.back();
while (!parent.has_leaf()) {
parents.push_back({parent, parent.begin()});
node_offset = (*parents.back().iterator).value();
parent = dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset);
}
iterator res{block().get(), std::move(nodes)};
iterator res{block().get(), std::move(parents), parent.leaf()};
if (!res.is_begin())
--res;
return res;
} else {
// Since we are bigger lexicographical, we need to go to the last node
while (node.iterator = node.node->end(), !(--node.iterator).is_leaf_value()) {
node_offset = (*node.iterator).value;
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block().get(), node_offset)});
node = nodes.back();
while (parent.size()) {
parents.push_back({parent, --parent.end()});
node_offset = (*parents.back().iterator).value();
parent = dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset);
}
return {block().get(), std::move(nodes)};
assert(parent.has_leaf());
return {block().get(), std::move(parents), parent.leaf()};
}
}
}
Expand All @@ -121,36 +129,35 @@ class DirectoryTree : public SubBlockAllocator<DirectoryTreeHeader> {
std::pair<iterator, std::string_view::const_iterator> find_for_insert(std::string_view key) const {
if (size() == 0)
return {end(), {}};
std::deque<typename iterator::node_info> nodes;
std::deque<typename iterator::parent_node_info> parents;
uint16_t node_offset = extra_header()->root.value();
auto current_key = key.begin();
while (true) {
nodes.push_back({dir_tree_node_ref::create<LeafValueType>(block(), node_offset)});
auto& node = nodes.back();
auto prefix = node.node->prefix();
decltype(iterator::parent_node_info::node) parent{
dir_tree_node_ref<LeafValueType>::create(block().get(), node_offset)};
auto prefix = parent.prefix();
auto [key_it, prefix_it] = std::ranges::mismatch(std::ranges::subrange(current_key, key.end()), prefix);
if (key_it == key.end()) {
// Got to end of our key
node.iterator = node.node->begin();
if (prefix_it == prefix.end()) {
// Full match, check if there is a node
if (node.iterator.is_leaf_value()) {
if (parent.has_leaf()) {
// Found exact match!
return {{block(), std::move(nodes)}, prefix_it};
return {{block().get(), std::move(parents), parent.leaf()}, prefix_it};
}
}
} else if (prefix_it == prefix.end()) {
// Got to end of prefix, but there is still more key
node.iterator = node.node->find(*key_it, /*exact_match=*/false);
if ((*node.iterator).key == *key_it) {
// Match, continue searching
auto iterator = parent.find(*key_it, /*exact_match=*/false);
if (iterator != parent.end() && (*iterator).key() >= *key_it) {
current_key = key_it + 1;
node_offset = (*node.iterator).value;
node_offset = (*iterator).value();
parents.push_back({parent, iterator});
continue;
}
}
// Mismatch
return {{block(), std::move(nodes)}, prefix_it};
return {{block(), std::move(parents), {}}, prefix_it};
}
}
};
Loading