This file is indexed.

/usr/include/dballe/db/summary.h is in libdballe-dev 7.7-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#ifndef DBALLE_DB_SUMMARY_H
#define DBALLE_DB_SUMMARY_H

#include <dballe/core/query.h>
#include <dballe/db/db.h>
#include <vector>
#include <set>

namespace dballe {
namespace db {

class Matcher;
class Summary;

namespace summary {

/// Represent whether a summary can satisfy a given query
enum Support
{
    /// It cannot.
    UNSUPPORTED = 0,
    /// The query may select less data than this summary can estimate.
    OVERESTIMATED = 1,
    /// The query selects data that this summary can estimate exactly.
    EXACT = 2,
};

struct Entry
{
    int ana_id;
    std::string rep_memo;
    dballe::Level level;
    dballe::Trange trange;
    wreport::Varcode varcode;
    dballe::DatetimeRange dtrange;
    int count = MISSING_INT;

    Entry(db::CursorSummary& cur, bool want_details);
};

}

/**
 * High level objects for working with DB-All.e DB summaries
 */
class Summary
{
protected:
    // Query that generated this summary
    core::Query query;

    // Summary of items for the currently active filter
    std::vector<summary::Entry> summary;

    void aggregate(const summary::Entry& entry);

public:
    Summary(const dballe::Query& query);

    // True if the summary has been filled with data
    bool valid = false;

    std::set<int> all_stations;
    std::set<std::string> all_reports;
    std::set<dballe::Level> all_levels;
    std::set<dballe::Trange> all_tranges;
    std::set<wreport::Varcode> all_varcodes;

    // Last known datetime range for the data that we have
    dballe::DatetimeRange dtrange;
    // Last known count for the data that we have
    unsigned count = MISSING_INT;

    /// Return true if the summary has been filled with data
    bool is_valid() const { return valid; }

    const Datetime& datetime_min() const { return dtrange.min; }
    const Datetime& datetime_max() const { return dtrange.max; }
    unsigned data_count() const { return count; }

    /**
     * Checks if this summary correctly generate a
     * summary for the given query.
     */
    summary::Support supports(const Query& query) const;

    /// Add an entry to the summary taken from the current status of \a cur
    void add_summary(db::CursorSummary& cur, bool with_details);

    /// Add a copy of an existing entry
    void add_entry(const summary::Entry& entry);

    /// Iterate all values in the summary
    bool iterate(std::function<bool(const summary::Entry&)> f) const;
};

namespace summary {

/**
 * Stack of summary in increasing order of selectivity.
 *
 * This is used to keep enough context to refine a summary as a query is
 * refined, and to go back to a wider summary if the query is relaxed.
 *
 * Ideally, there could be several levels in the stack, so that each subquery
 * takes the previous one as a starting point, and the process gets faster and
 * faster; however, a summary may support a query (in the sense that it knows
 * that that query selects no data at all) while a more general summary may
 * support it and return data (e.g. ask first for rep_memo=synop, then change
 * one's mind and ask for rep_memo=temp.
 *
 * Supporting such scenarios would require implementing nontrivial logic for an
 * optimization that it is still unclear to me if it would be required. At the
 * moment, I simplify implementation by just supporting two levels, and having
 * each query always start from the topmost summary.
 */
class Stack
{
protected:
    /**
     * Summaries for the current query.
     *
     * summaries[0] is always the summary for the whole database;
     * further summaries are appended as the query is refined.
     */
    std::vector<Summary> summaries;

public:
    /// Check if the stack is empty
    bool empty() const { return summaries.empty(); }

    /// Return the stack size. Only really useful for tests.
    unsigned size() const { return summaries.size(); }

    /// Add a new summary to the stack, and return a reference to it
    Summary& push(const Query& query);

    /// Return the topmost summary
    const Summary& top() const { return summaries.back(); }

    /**
     * If the current summary stack can support the given query, append the
     * resulting summary to the stack, else, remove all entries from the stack
     * except the most general one.
     *
     * @returns how the resulting stack supports the query.
     */
    Support query(const Query& query, bool exact, std::function<bool(const Entry&)> match);
};

}

}
}

#endif