Cavil-Matcher
view release on metacpan or search on metacpan
src/matcher.cc view on Meta::CPAN
// SPDX-FileCopyrightText: SUSE LLC
// SPDX-License-Identifier: GPL-2.0-or-later
#include "matcher.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <map>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
// Same safety limit as the previous engine: lines longer than this are read in chunks by fgets, so a
// giant single-line file never overflows the buffer.
static const int MAX_LINE_SIZE = 8000;
MappedFile::~MappedFile() {
if (_data && _data != MAP_FAILED) munmap((void*)_data, _size);
if (_fd >= 0) close(_fd);
}
bool MappedFile::map(const std::string& path) {
_fd = open(path.c_str(), O_RDONLY);
if (_fd < 0) return false;
struct stat st;
if (fstat(_fd, &st) != 0 || st.st_size <= 0) {
close(_fd);
_fd = -1;
return false;
}
void* p = mmap(nullptr, (size_t)st.st_size, PROT_READ, MAP_SHARED, _fd, 0);
if (p == MAP_FAILED) {
close(_fd);
_fd = -1;
return false;
}
_data = static_cast<const char*>(p);
_size = (size_t)st.st_size;
return true;
}
void Matcher::clear() {
_build = BuildTrie();
_build_dirty = false;
_build_segment = Segment();
_segments.clear();
_maps.clear();
_tombstones.clear();
}
void Matcher::add_pattern(uint32_t id, const std::vector<uint64_t>& tokens) {
_build.add_pattern(id, tokens);
_build_dirty = true;
}
void Matcher::set_tombstones(const std::vector<uint32_t>& ids) {
_tombstones.clear();
for (uint32_t id : ids) _tombstones.insert(id);
}
bool Matcher::attach(const std::string& path) {
auto mf = std::make_unique<MappedFile>();
if (!mf->map(path)) return false;
auto seg = std::make_unique<Segment>();
// Trusted scan path: skip the whole-payload CRC (verified at publish), keep structural validation.
if (!seg->open(mf->data(), mf->size(), /*verify_crc=*/false)) return false;
_maps.push_back(std::move(mf));
_segments.push_back(std::move(seg));
return true;
}
bool Matcher::verify(const std::string& path) const {
// Full integrity check (CRC + structure) of a segment file, for an explicit fsck. The scan path
// (load/attach) trusts the CRC of the immutable published cache; this is how it is proven on demand.
MappedFile mf;
if (!mf.map(path)) return false;
Segment seg;
return seg.open(mf.data(), mf.size(), /*verify_crc=*/true);
}
bool Matcher::dump(const std::string& path) {
std::vector<char> buf = _build.compile(_generation);
// Publish is the one place integrity is proven: full-verify (CRC + structure) the freshly compiled
// buffer before it is written, so the scan path can safely trust this immutable file without re-CRCing
// it on every open. A buffer that fails here is never published.
( run in 3.340 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )