81 lines
3.1 KiB
C++
81 lines
3.1 KiB
C++
#pragma once
|
|
#include "query.hpp"
|
|
#include <deque>
|
|
|
|
namespace wl {
|
|
struct Entry {
|
|
uint64_t id = 0, parent = 0, size = 0, modified = 0, created = 0, accessed = 0;
|
|
uint32_t attributes = 0, name = 0, next_name = no_row, parent_row = no_row;
|
|
};
|
|
struct Name {
|
|
std::string text, lower;
|
|
uint32_t first = no_row;
|
|
};
|
|
struct RawEntry {
|
|
uint64_t id = 0, parent = 0, size = 0, modified = 0, created = 0, accessed = 0;
|
|
uint32_t attributes = 0;
|
|
std::string name;
|
|
};
|
|
class Volume {
|
|
public:
|
|
mutable std::shared_mutex mutex;
|
|
std::string root;
|
|
uint64_t serial = 0, root_id = 0, journal_id = 0, next_usn = 0, generation = 1, name_generation = 1;
|
|
uint64_t checkpoint_usn = 0;
|
|
uint64_t pending_updates = 0;
|
|
uint64_t files = 0, directories = 0;
|
|
bool ready = false;
|
|
std::string state = "indexing";
|
|
std::vector<Entry> entries;
|
|
std::deque<Name> names;
|
|
std::vector<uint32_t> sorted_names;
|
|
std::unordered_map<uint64_t, uint32_t> directory_rows;
|
|
explicit Volume(std::string source) : root(std::move(source)) {}
|
|
void add_initial(RawEntry record);
|
|
void finish();
|
|
void compact();
|
|
void replace_links(uint64_t id, const std::vector<RawEntry>& records);
|
|
std::string full_path(uint32_t row) const;
|
|
Result result(uint32_t row, bool with_path = true) const;
|
|
std::vector<uint32_t> find(const Query& query, uint64_t stop_after, const std::function<bool()>& cancelled, bool ordered = false) const;
|
|
void save(const std::filesystem::path& path) const;
|
|
static std::shared_ptr<Volume> load(const std::filesystem::path& path, std::string root, uint64_t serial);
|
|
private:
|
|
std::unordered_map<std::string_view, uint32_t> name_ids_;
|
|
std::vector<uint64_t> name_masks_;
|
|
std::unordered_map<uint64_t, std::vector<uint32_t>> added_ids_;
|
|
// Intrusive child chains use four bytes per row, with one head per parent.
|
|
// Keying heads by NTFS file reference preserves descendants on directory moves.
|
|
std::unordered_map<uint64_t, uint32_t> first_children_;
|
|
std::vector<uint32_t> next_sibling_;
|
|
size_t base_count_ = 0, sorted_name_count_ = 0;
|
|
uint32_t intern(std::string name);
|
|
void add(RawEntry record, bool delta);
|
|
std::vector<uint32_t> rows_for_id(uint64_t id) const;
|
|
uint32_t parent_row(uint32_t row) const;
|
|
void link_child(uint32_t row);
|
|
void unlink_child(uint32_t row);
|
|
std::vector<uint32_t> find_literals(const Query& query, const std::vector<std::string_view>& literals,
|
|
uint64_t stop_after, const std::function<bool()>& cancelled, bool ordered) const;
|
|
};
|
|
struct RowRef { uint32_t volume, row; };
|
|
class Engine {
|
|
public:
|
|
mutable std::shared_mutex mutex;
|
|
std::vector<std::shared_ptr<Volume>> volumes;
|
|
Reply search(const Request& request, const std::function<bool()>& cancelled = [] { return false; });
|
|
Reply status() const;
|
|
void set_volumes(std::vector<std::shared_ptr<Volume>> value);
|
|
private:
|
|
struct Cached {
|
|
Request request;
|
|
uint64_t generation = 0;
|
|
std::vector<std::shared_ptr<Volume>> volumes;
|
|
std::vector<RowRef> rows;
|
|
};
|
|
std::mutex cache_mutex_;
|
|
std::shared_ptr<Cached> cache_;
|
|
uint64_t topology_ = 1;
|
|
};
|
|
}
|