mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-12 22:10:54 -04:00
add inode_ordering
This commit is contained in:
parent
f54ac8d50e
commit
b49dd782c6
@ -381,6 +381,7 @@ list(
|
||||
src/dwarfs/inode_chunkable.cpp
|
||||
src/dwarfs/inode_fragments.cpp
|
||||
src/dwarfs/inode_manager.cpp
|
||||
src/dwarfs/inode_ordering.cpp
|
||||
src/dwarfs/inode_reader_v2.cpp
|
||||
src/dwarfs/logger.cpp
|
||||
src/dwarfs/metadata_types.cpp
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "dwarfs/inode_fragments.h"
|
||||
#include "dwarfs/nilsimsa.h"
|
||||
#include "dwarfs/object.h"
|
||||
#include "dwarfs/sortable_span.h"
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
@ -62,4 +63,7 @@ class inode : public object {
|
||||
virtual void dump(std::ostream& os, inode_options const& options) const = 0;
|
||||
};
|
||||
|
||||
using sortable_inode_span =
|
||||
sortable_span<std::shared_ptr<inode> const, uint32_t>;
|
||||
|
||||
} // namespace dwarfs
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "dwarfs/fragment_category.h"
|
||||
#include "dwarfs/inode.h"
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
@ -79,6 +80,8 @@ class inode_manager {
|
||||
|
||||
void dump(std::ostream& os) const { impl_->dump(os); }
|
||||
|
||||
sortable_inode_span sortable_span() const { return impl_->sortable_span(); }
|
||||
|
||||
class impl {
|
||||
public:
|
||||
virtual ~impl() = default;
|
||||
@ -96,6 +99,7 @@ class inode_manager {
|
||||
scan_background(worker_group& wg, os_access& os, std::shared_ptr<inode> ino,
|
||||
file const* p) const = 0;
|
||||
virtual void dump(std::ostream& os) const = 0;
|
||||
virtual sortable_inode_span sortable_span() const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
54
include/dwarfs/inode_ordering.h
Normal file
54
include/dwarfs/inode_ordering.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/**
|
||||
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||
*
|
||||
* This file is part of dwarfs.
|
||||
*
|
||||
* dwarfs is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dwarfs is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "dwarfs/inode.h"
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
class logger;
|
||||
|
||||
class inode_ordering {
|
||||
public:
|
||||
inode_ordering(logger& lgr);
|
||||
|
||||
void by_inode_number(sortable_inode_span& sp) const {
|
||||
impl_->by_inode_number(sp);
|
||||
}
|
||||
|
||||
void by_path(sortable_inode_span& sp) const { impl_->by_path(sp); }
|
||||
|
||||
class impl {
|
||||
public:
|
||||
virtual ~impl() = default;
|
||||
|
||||
virtual void by_inode_number(sortable_inode_span& sp) const = 0;
|
||||
virtual void by_path(sortable_inode_span& sp) const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
std::unique_ptr<impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace dwarfs
|
119
include/dwarfs/sortable_span.h
Normal file
119
include/dwarfs/sortable_span.h
Normal file
@ -0,0 +1,119 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/**
|
||||
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||
*
|
||||
* This file is part of dwarfs.
|
||||
*
|
||||
* dwarfs is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dwarfs is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <numeric>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
template <typename T, typename IndexValueType = size_t>
|
||||
class sortable_span {
|
||||
public:
|
||||
using value_type = T;
|
||||
using index_value_type = IndexValueType;
|
||||
|
||||
class iterator
|
||||
: public boost::iterator_facade<iterator, value_type,
|
||||
boost::random_access_traversal_tag> {
|
||||
public:
|
||||
using difference_type = typename boost::iterator_facade<
|
||||
iterator, value_type,
|
||||
boost::random_access_traversal_tag>::difference_type;
|
||||
|
||||
iterator() = default;
|
||||
iterator(iterator const& other) = default;
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
friend class sortable_span;
|
||||
|
||||
iterator(sortable_span const* vv,
|
||||
typename std::vector<index_value_type>::iterator it)
|
||||
: vv_(vv)
|
||||
, it_(it) {}
|
||||
|
||||
bool equal(iterator const& other) const {
|
||||
return vv_ == other.vv_ && it_ == other.it_;
|
||||
}
|
||||
|
||||
void increment() { ++it_; }
|
||||
|
||||
void decrement() { --it_; }
|
||||
|
||||
void advance(difference_type n) { it_ += n; }
|
||||
|
||||
difference_type distance_to(iterator const& other) const {
|
||||
return other.it_ - it_;
|
||||
}
|
||||
|
||||
value_type& dereference() const { return vv_->values_[*it_]; }
|
||||
|
||||
sortable_span const* vv_{nullptr};
|
||||
typename std::vector<index_value_type>::iterator it_;
|
||||
};
|
||||
|
||||
explicit sortable_span(std::span<value_type> values)
|
||||
: values_{values} {}
|
||||
|
||||
template <typename P>
|
||||
void select(P& predicate) {
|
||||
index_.reserve(values_.size());
|
||||
for (size_t i = 0; i < values_.size(); ++i) {
|
||||
if (predicate(values_[i])) {
|
||||
index_.push_back(i);
|
||||
}
|
||||
}
|
||||
index_.shrink_to_fit();
|
||||
}
|
||||
|
||||
void all() {
|
||||
index_.resize(values_.size());
|
||||
std::iota(index_.begin(), index_.end(), 0);
|
||||
}
|
||||
|
||||
bool empty() const { return index_.empty(); }
|
||||
size_t size() const { return index_.size(); }
|
||||
|
||||
value_type const& operator[](size_t i) const {
|
||||
return proxy(this, index_.begin() + i);
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(this, index_.begin()); }
|
||||
|
||||
iterator end() { return iterator(this, index_.end()); }
|
||||
|
||||
std::vector<index_value_type>& index() { return index_; }
|
||||
std::vector<index_value_type> const& index() const { return index_; }
|
||||
|
||||
std::span<value_type> raw() const { return values_; }
|
||||
|
||||
private:
|
||||
std::vector<index_value_type> index_;
|
||||
std::span<value_type> const values_;
|
||||
};
|
||||
|
||||
} // namespace dwarfs
|
@ -43,8 +43,8 @@
|
||||
#include "dwarfs/compiler.h"
|
||||
#include "dwarfs/entry.h"
|
||||
#include "dwarfs/error.h"
|
||||
#include "dwarfs/inode.h"
|
||||
#include "dwarfs/inode_manager.h"
|
||||
#include "dwarfs/inode_ordering.h"
|
||||
#include "dwarfs/logger.h"
|
||||
#include "dwarfs/mmif.h"
|
||||
#include "dwarfs/nilsimsa.h"
|
||||
@ -526,14 +526,11 @@ class inode_manager_ final : public inode_manager::impl {
|
||||
void for_each_inode_in_order(
|
||||
std::function<void(std::shared_ptr<inode> const&)> const& fn)
|
||||
const override {
|
||||
std::vector<uint32_t> index;
|
||||
index.resize(inodes_.size());
|
||||
std::iota(index.begin(), index.end(), size_t(0));
|
||||
std::sort(index.begin(), index.end(), [this](size_t a, size_t b) {
|
||||
return inodes_[a]->num() < inodes_[b]->num();
|
||||
});
|
||||
for (auto i : index) {
|
||||
fn(inodes_[i]);
|
||||
auto span = sortable_span();
|
||||
span.all();
|
||||
inode_ordering(LOG_GET_LOGGER).by_inode_number(span);
|
||||
for (auto const& i : span) {
|
||||
fn(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,6 +582,10 @@ class inode_manager_ final : public inode_manager::impl {
|
||||
|
||||
void dump(std::ostream& os) const override;
|
||||
|
||||
sortable_inode_span sortable_span() const override {
|
||||
return sortable_inode_span(inodes_);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool inodes_need_scanning(inode_options const& opts) {
|
||||
if (opts.categorizer_mgr) {
|
||||
@ -599,27 +600,11 @@ class inode_manager_ final : public inode_manager::impl {
|
||||
}
|
||||
|
||||
void order_inodes_by_path() {
|
||||
std::vector<std::string> paths;
|
||||
std::vector<size_t> index(inodes_.size());
|
||||
|
||||
paths.reserve(inodes_.size());
|
||||
|
||||
for (auto const& ino : inodes_) {
|
||||
paths.emplace_back(ino->any()->path_as_string());
|
||||
}
|
||||
|
||||
std::iota(index.begin(), index.end(), size_t(0));
|
||||
|
||||
std::sort(index.begin(), index.end(),
|
||||
[&](size_t a, size_t b) { return paths[a] < paths[b]; });
|
||||
|
||||
std::vector<std::shared_ptr<inode>> tmp;
|
||||
tmp.reserve(inodes_.size());
|
||||
|
||||
for (size_t ix : index) {
|
||||
tmp.emplace_back(inodes_[ix]);
|
||||
}
|
||||
auto span = sortable_span();
|
||||
span.all();
|
||||
inode_ordering(LOG_GET_LOGGER).by_path(span);
|
||||
|
||||
std::vector<std::shared_ptr<inode>> tmp(span.begin(), span.end());
|
||||
inodes_.swap(tmp);
|
||||
}
|
||||
|
||||
|
72
src/dwarfs/inode_ordering.cpp
Normal file
72
src/dwarfs/inode_ordering.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/**
|
||||
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||
*
|
||||
* This file is part of dwarfs.
|
||||
*
|
||||
* dwarfs is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* dwarfs is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "dwarfs/entry.h"
|
||||
#include "dwarfs/inode_ordering.h"
|
||||
#include "dwarfs/logger.h"
|
||||
|
||||
namespace dwarfs {
|
||||
|
||||
template <typename LoggerPolicy>
|
||||
class inode_ordering_ final : public inode_ordering::impl {
|
||||
public:
|
||||
inode_ordering_(logger& lgr)
|
||||
: LOG_PROXY_INIT(lgr) {}
|
||||
|
||||
void by_inode_number(sortable_inode_span& sp) const override;
|
||||
void by_path(sortable_inode_span& sp) const override;
|
||||
|
||||
private:
|
||||
LOG_PROXY_DECL(LoggerPolicy);
|
||||
};
|
||||
|
||||
template <typename LoggerPolicy>
|
||||
void inode_ordering_<LoggerPolicy>::by_inode_number(
|
||||
sortable_inode_span& sp) const {
|
||||
std::sort(
|
||||
sp.index().begin(), sp.index().end(),
|
||||
[r = sp.raw()](auto a, auto b) { return r[a]->num() < r[b]->num(); });
|
||||
}
|
||||
|
||||
template <typename LoggerPolicy>
|
||||
void inode_ordering_<LoggerPolicy>::by_path(sortable_inode_span& sp) const {
|
||||
std::vector<std::string> paths;
|
||||
|
||||
auto raw = sp.raw();
|
||||
auto& index = sp.index();
|
||||
|
||||
paths.resize(raw.size());
|
||||
|
||||
for (auto i : index) {
|
||||
paths[i] = raw[i]->any()->path_as_string();
|
||||
}
|
||||
|
||||
std::sort(index.begin(), index.end(),
|
||||
[&](auto a, auto b) { return paths[a] < paths[b]; });
|
||||
}
|
||||
|
||||
inode_ordering::inode_ordering(logger& lgr)
|
||||
: impl_(make_unique_logging_object<impl, inode_ordering_, logger_policies>(
|
||||
lgr)) {}
|
||||
|
||||
} // namespace dwarfs
|
Loading…
x
Reference in New Issue
Block a user