Commit cb910c1f authored by Ramon Nou's avatar Ramon Nou
Browse files

fix(metadata): restore whole-path regex matching for filtered scans

parent 33e98104
Loading
Loading
Loading
Loading
Loading
+3 −1
Changes for src/daemon/backend/metadata/rocksdb_backend.cpp: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -798,7 +798,9 @@ RocksDBBackend::get_dirents_filtered_impl(
        scanned_count++;

        bool matched = !S_ISDIR(mode);
        if(use_regex && !std::regex_search(std::string(rel_name), name_regex)) {
        // Preserve 0.9.6 whole-path matching. Substring regex_search with
        // wildcard filters such as .*01.* retries nonmatching path suffixes.
        if(use_regex && !std::regex_match(std::string(rel_name), name_regex)) {
            matched = false;
        }
        if(matched && filter_size != -1 && size != (size_t) filter_size) {
+14 −11
Changes for tests/integration/directories/test_sfind_filtered.py: 14 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -68,12 +68,12 @@ def test_sfind_filtered(test_workspace, request, monkeypatch, buffer_size,
        ret = io_client.create_n_files(str(nested_dir), 10)
        assert ret.retval == 0

        # Search for "file_5" in the scoped subdir (should be file_5)
        # Server filters match the entire relative path, including subdirs.
        log.info(
            f"Running recursive sfind command: {sfind_bin} {test_dir} "
            "-regex \"(^|/)file_5$\" ...")
            "-regex \"(^|.*/)file_5$\" ...")
        # Should find file_5 in top dir AND file_5 in subdir
        ret = shell.run(str(sfind_bin), str(test_dir), "-regex", "(^|/)file_5$",
        ret = shell.run(str(sfind_bin), str(test_dir), "-regex", "(^|.*/)file_5$",
                        "-M", str(mount_dir), "-S", "1", "--server-side")

        sfind_stdout = ret.stdout.decode(errors='replace') if ret.stdout else ""
@@ -86,14 +86,18 @@ def test_sfind_filtered(test_workspace, request, monkeypatch, buffer_size,
        # Matches: 2
        assert "MATCHED 2/111" in sfind_stdout

        # Both implementations must scan descendants, exclude directories
        # from matches, and report exact counts regardless of buffer size.
        # Both implementations scan descendants and exclude directories.
        # Server-side filters retain 0.9.6 whole-path matching, whereas the
        # client-side implementation uses substring matching.
        for server_side in (False, True):
            for count_only in (False, True):
                for pattern, expected in (("*file_5", 12),
                                          ("file_5", 12),
                                          ("*", 110),
                                          ("missing", 0)):
                for pattern, server_expected, client_expected in (
                        ("*file_5", 2, 12),
                        ("file_5", 1, 12),
                        ("*file_5*", 12, 12),
                        ("*", 110, 110),
                        ("missing", 0, 0)):
                    expected = server_expected if server_side else client_expected
                    flags = []
                    if server_side:
                        flags.append("--server-side")
@@ -110,8 +114,7 @@ def test_sfind_filtered(test_workspace, request, monkeypatch, buffer_size,
                    if server_side and not count_only and pattern == "*file_5":
                        paths = {line for line in stdout.splitlines()
                                 if line.startswith(str(test_dir) + "/")}
                        assert paths == {str(test_dir / ("file_%d" % i))
                                         for i in [5] + list(range(50, 60))} | {
                        assert paths == {str(test_dir / "file_5"),
                                         str(nested_dir / "file_5")}

        # Failed RPCs must not be presented as a successful empty scan.