• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 19767129845-2720

28 Nov 2025 02:48PM UTC coverage: 68.859% (-0.07%) from 68.93%
19767129845-2720

push

github

tstack
[formats] add idea_log

Related to #1597

51227 of 74394 relevant lines covered (68.86%)

435625.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.54
/src/logfile_sub_source.hh
1
/**
2
 * Copyright (c) 2007-2012, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * @file logfile_sub_source.hh
30
 */
31

32
#ifndef logfile_sub_source_hh
33
#define logfile_sub_source_hh
34

35
#include <array>
36
#include <utility>
37
#include <vector>
38

39
#include <limits.h>
40

41
#include "base/time_util.hh"
42
#include "big_array.hh"
43
#include "bookmarks.hh"
44
#include "document.sections.hh"
45
#include "filter_observer.hh"
46
#include "log_format.hh"
47
#include "logfile.hh"
48
#include "strong_int.hh"
49
#include "textview_curses.hh"
50

51
STRONG_INT_TYPE(uint64_t, content_line);
52

53
struct sqlite3_stmt;
54
extern "C"
55
{
56
int sqlite3_finalize(sqlite3_stmt* pStmt);
57
}
58

59
class logfile_sub_source;
60

61
class index_delegate {
62
public:
63
    virtual ~index_delegate() = default;
×
64

65
    virtual void index_start(logfile_sub_source& lss) {}
×
66

67
    virtual void index_line(logfile_sub_source& lss,
×
68
                            logfile* lf,
69
                            logfile::iterator ll)
70
    {
71
    }
72

73
    virtual void index_complete(logfile_sub_source& lss) {}
×
74
};
75

76
class sql_filter : public text_filter {
77
public:
78
    sql_filter(logfile_sub_source& lss,
7✔
79
               std::string stmt_str,
80
               sqlite3_stmt* stmt)
81
        : text_filter(EXCLUDE, filter_lang_t::SQL, std::move(stmt_str), 0),
7✔
82
          sf_log_source(lss)
7✔
83
    {
84
        this->sf_filter_stmt = stmt;
7✔
85
    }
7✔
86

87
    bool matches(std::optional<line_source> ls,
88
                 const shared_buffer_ref& line) override;
89

90
    std::string to_command() const override;
91

92
    auto_mem<sqlite3_stmt> sf_filter_stmt{sqlite3_finalize};
93
    logfile_sub_source& sf_log_source;
94
};
95

96
class log_location_history : public location_history {
97
public:
98
    explicit log_location_history(logfile_sub_source& lss)
1,167✔
99
        : llh_history(std::begin(this->llh_backing),
2,334✔
100
                      std::end(this->llh_backing)),
1,167✔
101
          llh_log_source(lss)
1,167✔
102
    {
103
    }
1,167✔
104

105
    ~log_location_history() override = default;
757✔
106

107
    void loc_history_append(vis_line_t top) override;
108

109
    std::optional<vis_line_t> loc_history_back(vis_line_t current_top) override;
110

111
    std::optional<vis_line_t> loc_history_forward(
112
        vis_line_t current_top) override;
113

114
private:
115
    nonstd::ring_span<content_line_t> llh_history;
116
    logfile_sub_source& llh_log_source;
117
    content_line_t llh_backing[MAX_SIZE];
118
};
119

120
class logline_window;
121

122
/**
123
 * Delegate class that merges the contents of multiple log files into a single
124
 * source of data for a text view.
125
 */
126
class logfile_sub_source
127
    : public text_sub_source
128
    , public text_time_translator
129
    , public text_accel_source
130
    , public list_input_delegate
131
    , public text_anchors
132
    , public text_delegate
133
    , public text_detail_provider
134
    , public lnav_config_listener {
135
public:
136
    const static bookmark_type_t BM_FILES;
137

138
    virtual void text_filters_changed();
139

140
    logfile_sub_source();
141

142
    ~logfile_sub_source() = default;
757✔
143

144
    enum class line_context_t : uint8_t {
145
        filename,
146
        basename,
147
        none,
148
        time_column,
149
    };
150

151
    void increase_line_context();
152

153
    bool decrease_line_context();
154

155
    size_t get_filename_offset() const;
156

157
    line_context_t get_line_context() const { return this->lss_line_context; }
13✔
158

159
    log_level_t get_min_log_level() const { return this->lss_min_log_level; }
6✔
160

161
    void set_force_rebuild() { this->lss_force_rebuild = true; }
11✔
162

163
    bool is_rebuild_forced() const { return this->lss_force_rebuild; }
83✔
164

165
    void set_min_log_level(log_level_t level)
9✔
166
    {
167
        if (this->lss_min_log_level != level) {
9✔
168
            this->lss_min_log_level = level;
3✔
169
            this->text_filters_changed();
3✔
170
        }
171
    }
9✔
172

173
    bool list_input_handle_key(listview_curses& lv, const ncinput& ch);
174

175
    void set_marked_only(bool val)
8✔
176
    {
177
        if (this->lss_marked_only != val) {
8✔
178
            this->lss_marked_only = val;
2✔
179
            this->text_filters_changed();
2✔
180
        }
181
    }
8✔
182

183
    void update_filter_hash_state(hasher& h) const;
184

185
    bool get_marked_only() { return this->lss_marked_only; }
×
186

187
    size_t text_line_count() { return this->lss_filtered_index.size(); }
29,254✔
188

189
    size_t text_line_width(textview_curses& curses)
7,936✔
190
    {
191
        return this->lss_longest_line;
7,936✔
192
    }
193

194
    size_t file_count() const;
195

196
    bool empty() const { return this->lss_filtered_index.empty(); }
×
197

198
    line_info text_value_for_line(textview_curses& tc,
199
                                  int row,
200
                                  std::string& value_out,
201
                                  line_flags_t flags);
202

203
    void text_attrs_for_line(textview_curses& tc,
204
                             int row,
205
                             string_attrs_t& value_out);
206

207
    size_t text_size_for_line(textview_curses& tc, int row, line_flags_t flags);
208

209
    void text_mark(const bookmark_type_t* bm, vis_line_t line, bool added);
210

211
    void text_clear_marks(const bookmark_type_t* bm);
212

213
    bool insert_file(const std::shared_ptr<logfile>& lf);
214

215
    void remove_file(std::shared_ptr<logfile> lf);
216

217
    enum class rebuild_result {
218
        rr_no_change,
219
        rr_appended_lines,
220
        rr_partial_rebuild,
221
        rr_full_rebuild,
222
    };
223

224
    rebuild_result rebuild_index(std::optional<ui_clock::time_point> deadline
225
                                 = std::nullopt);
226

227
    void text_update_marks(vis_bookmarks& bm);
228

229
    void set_user_mark(const bookmark_type_t* bm, content_line_t cl)
29✔
230
    {
231
        this->lss_user_marks[bm].insert_once(cl);
29✔
232
    }
29✔
233

234
    bookmarks<content_line_t>::type& get_user_bookmarks()
23✔
235
    {
236
        return this->lss_user_marks;
23✔
237
    }
238

239
    bookmark_metadata& get_bookmark_metadata(content_line_t cl);
240

241
    bookmark_metadata& get_bookmark_metadata(vis_line_t vl)
25✔
242
    {
243
        return this->get_bookmark_metadata(this->at(vl));
25✔
244
    }
245

246
    struct bookmark_metadata_context {
247
        std::optional<vis_line_t> bmc_current;
248
        std::optional<bookmark_metadata*> bmc_current_metadata;
249
        std::optional<vis_line_t> bmc_next_line;
250
    };
251

252
    bookmark_metadata_context get_bookmark_metadata_context(
253
        vis_line_t vl,
254
        bookmark_metadata::categories desired
255
        = bookmark_metadata::categories::any) const;
256

257
    std::optional<bookmark_metadata*> find_bookmark_metadata(
258
        content_line_t cl) const;
259

260
    std::optional<bookmark_metadata*> find_bookmark_metadata(
23,218✔
261
        vis_line_t vl) const
262
    {
263
        if (vl >= vis_line_t(this->lss_filtered_index.size())) {
23,218✔
264
            return std::nullopt;
×
265
        }
266
        return this->find_bookmark_metadata(this->at(vl));
23,218✔
267
    }
268

269
    void erase_bookmark_metadata(content_line_t cl);
270

271
    void erase_bookmark_metadata(vis_line_t vl)
26✔
272
    {
273
        this->erase_bookmark_metadata(this->at(vl));
26✔
274
    }
26✔
275

276
    void clear_bookmark_metadata();
277

278
    int get_filtered_count() const
1,835✔
279
    {
280
        return this->lss_index.size() - this->lss_filtered_index.size();
1,835✔
281
    }
282

283
    int get_filtered_count_for(size_t filter_index) const;
284

285
    Result<void, lnav::console::user_message> set_sql_filter(
286
        std::string stmt_str, sqlite3_stmt* stmt);
287

288
    Result<void, lnav::console::user_message> set_sql_marker(
289
        std::string stmt_str, sqlite3_stmt* stmt);
290

291
    Result<void, lnav::console::user_message> set_preview_sql_filter(
292
        sqlite3_stmt* stmt);
293

294
    std::string get_sql_filter_text()
51✔
295
    {
296
        auto filt = this->get_sql_filter();
51✔
297

298
        if (filt) {
51✔
299
            return filt.value()->get_id();
1✔
300
        }
301
        return "";
100✔
302
    }
51✔
303

304
    std::optional<std::shared_ptr<text_filter>> get_sql_filter();
305

306
    std::string get_sql_marker_text() const
47✔
307
    {
308
        return this->lss_marker_stmt_text;
47✔
309
    }
310

311
    std::shared_ptr<logfile> find(const char* fn, content_line_t& line_base);
312

313
    std::shared_ptr<logfile> find(content_line_t& line) const
27,382✔
314
    {
315
        std::shared_ptr<logfile> retval;
27,382✔
316

317
        retval = this->lss_files[line / MAX_LINES_PER_FILE]->get_file();
27,382✔
318
        line = content_line_t(line % MAX_LINES_PER_FILE);
27,382✔
319

320
        return retval;
27,382✔
321
    }
322

323
    logfile* find_file_ptr(content_line_t& line) const
349,856✔
324
    {
325
        auto* retval
326
            = this->lss_files[line / MAX_LINES_PER_FILE]->get_file_ptr();
349,856✔
327
        line = content_line_t(line % MAX_LINES_PER_FILE);
349,856✔
328

329
        return retval;
349,856✔
330
    }
331

332
    logline* find_line(content_line_t line) const
221,785✔
333
    {
334
        logline* retval = nullptr;
221,785✔
335
        auto lf = this->find_file_ptr(line);
221,785✔
336

337
        if (lf != nullptr) {
221,785✔
338
            auto ll_iter = lf->begin() + line;
221,785✔
339

340
            retval = &(*ll_iter);
221,785✔
341
        }
342

343
        return retval;
221,785✔
344
    }
345

346
    std::optional<std::pair<std::shared_ptr<logfile>, logfile::iterator>>
347
    find_line_with_file(content_line_t line) const
24,444✔
348
    {
349
        std::shared_ptr<logfile> lf = this->find(line);
24,444✔
350

351
        if (lf != nullptr) {
24,444✔
352
            auto ll_iter = lf->begin() + line;
24,444✔
353

354
            return std::make_pair(lf, ll_iter);
24,444✔
355
        }
356

357
        return std::nullopt;
×
358
    }
24,444✔
359

360
    std::optional<std::pair<std::shared_ptr<logfile>, logfile::iterator>>
361
    find_line_with_file(std::optional<vis_line_t> vl) const
747✔
362
    {
363
        if (vl && vl.value() >= 0_vl
1,494✔
364
            && vl.value() < vis_line_t(this->lss_filtered_index.size()))
1,494✔
365
        {
366
            return this->find_line_with_file(this->at(vl.value()));
747✔
367
        }
368

369
        return std::nullopt;
×
370
    }
371

372
    std::optional<vis_line_t> find_from_time(const timeval& start) const;
373

374
    std::optional<vis_line_t> find_from_time(time_t start) const
×
375
    {
376
        const auto tv = timeval{start, 0};
×
377

378
        return this->find_from_time(tv);
×
379
    }
380

381
    std::optional<vis_line_t> find_from_time(const exttm& etm) const
×
382
    {
383
        return this->find_from_time(etm.to_timeval());
×
384
    }
385

386
    std::optional<vis_line_t> find_from_content(content_line_t cl);
387

388
    std::optional<row_info> time_for_row(vis_line_t row)
5,398✔
389
    {
390
        if (row >= 0_vl && row < (ssize_t) this->lss_filtered_index.size()) {
5,398✔
391
            auto cl = this->at(row);
3,754✔
392
            return row_info{
7,508✔
393
                this->find_line(cl)->get_timeval(),
3,754✔
394
                (int64_t) cl,
3,754✔
395
            };
3,754✔
396
        }
397
        return std::nullopt;
1,644✔
398
    }
399

400
    std::optional<vis_line_t> row_for(const row_info& ri);
401

402
    std::optional<vis_line_t> row_for_time(struct timeval time_bucket)
56✔
403
    {
404
        return this->find_from_time(time_bucket);
56✔
405
    }
406

407
    content_line_t at(vis_line_t vl) const
238,778✔
408
    {
409
        return this->lss_index[this->lss_filtered_index[vl]].value();
238,778✔
410
    }
411

412
    size_t get_filtered_before() const
×
413
    {
414
        return this->lss_filtered_index.empty() ? 0
×
415
                                                : this->lss_filtered_index[0];
×
416
    }
417

418
    size_t get_filtered_after() const
×
419
    {
420
        if (this->lss_filtered_index.empty()) {
×
421
            return 0;
×
422
        }
423

424
        return this->lss_index.size() - this->lss_filtered_index.back() - 1;
×
425
    }
426

427
    content_line_t at_base(vis_line_t vl)
430✔
428
    {
429
        while (vl > 0_vl
430✔
430
               && this->find_line(this->at(vl))->get_sub_offset() != 0)
430✔
431
        {
432
            --vl;
×
433
        }
434

435
        return this->at(vl);
430✔
436
    }
437

438
    std::unique_ptr<logline_window> window_at(vis_line_t start_vl,
439
                                              vis_line_t end_vl);
440

441
    std::unique_ptr<logline_window> window_at(vis_line_t start_vl);
442

443
    std::unique_ptr<logline_window> window_to_end(vis_line_t start_vl);
444

445
    /**
446
     * Container for logfile references that keeps of how many lines in the
447
     * logfile have been indexed.
448
     */
449
    struct logfile_data {
450
        logfile_data(size_t index,
518✔
451
                     filter_stack& fs,
452
                     const std::shared_ptr<logfile>& lf)
453
            : ld_file_index(index), ld_filter_state(fs, lf),
518✔
454
              ld_visible(lf->is_indexing())
518✔
455
        {
456
            lf->set_logline_observer(&this->ld_filter_state);
518✔
457
            this->ld_file_ptr = lf.get();
518✔
458
        }
518✔
459

460
        void clear()
518✔
461
        {
462
            this->ld_filter_state.lfo_filter_state.clear();
518✔
463
            this->ld_file_ptr = nullptr;
518✔
464
        }
518✔
465

466
        void set_file(const std::shared_ptr<logfile>& lf)
×
467
        {
468
            this->ld_filter_state.lfo_filter_state.tfs_logfile = lf;
×
469
            this->ld_file_ptr = lf.get();
×
470
            this->ld_lines_indexed = 0;
×
471
            this->ld_lines_watched = 0;
×
472
            this->ld_visible = lf->is_indexing();
×
473
            lf->set_logline_observer(&this->ld_filter_state);
×
474
        }
475

476
        std::shared_ptr<logfile> get_file() const
36,279✔
477
        {
478
            return this->ld_filter_state.lfo_filter_state.tfs_logfile;
36,279✔
479
        }
480

481
        logfile* get_file_ptr() const { return this->ld_file_ptr; }
488,997✔
482

483
        bool is_visible() const
15,643✔
484
        {
485
            return this->get_file_ptr() != nullptr && this->ld_visible;
15,643✔
486
        }
487

488
        void set_visibility(bool vis) { this->ld_visible = vis; }
525✔
489

490
        size_t ld_file_index;
491
        line_filter_observer ld_filter_state;
492
        size_t ld_lines_indexed{0};
493
        size_t ld_lines_watched{0};
494
        logfile* ld_file_ptr{nullptr};
495
        bool ld_visible;
496
    };
497

498
    using iterator = std::vector<std::unique_ptr<logfile_data>>::iterator;
499
    using const_iterator
500
        = std::vector<std::unique_ptr<logfile_data>>::const_iterator;
501

502
    size_t size() const { return this->lss_files.size(); }
×
503

504
    iterator begin() { return this->lss_files.begin(); }
1,680✔
505

506
    iterator end() { return this->lss_files.end(); }
1,866✔
507

508
    const_iterator cbegin() const { return this->lss_files.begin(); }
4,011✔
509

510
    const_iterator cend() const { return this->lss_files.end(); }
7,616✔
511

512
    iterator find_data(content_line_t& line)
4,034✔
513
    {
514
        auto retval = this->lss_files.begin();
4,034✔
515
        std::advance(retval, line / MAX_LINES_PER_FILE);
4,034✔
516
        line = content_line_t(line % MAX_LINES_PER_FILE);
4,034✔
517

518
        return retval;
4,034✔
519
    }
520

521
    iterator find_data(content_line_t line, uint64_t& offset_out)
101,963✔
522
    {
523
        auto retval = this->lss_files.begin();
101,963✔
524
        std::advance(retval, line / MAX_LINES_PER_FILE);
101,963✔
525
        offset_out = line % MAX_LINES_PER_FILE;
101,963✔
526

527
        return retval;
101,963✔
528
    }
529

530
    std::optional<logfile_data*> find_data(const std::shared_ptr<logfile>& lf)
53✔
531
    {
532
        for (auto& ld : *this) {
59✔
533
            if (ld->ld_filter_state.lfo_filter_state.tfs_logfile == lf) {
59✔
534
                return ld.get();
53✔
535
            }
536
        }
537
        return std::nullopt;
×
538
    }
539

540
    iterator find_data_i(const std::shared_ptr<const logfile>& lf)
121✔
541
    {
542
        for (auto iter = this->begin(); iter != this->end(); ++iter) {
122✔
543
            if ((*iter)->ld_filter_state.lfo_filter_state.tfs_logfile == lf) {
122✔
544
                return iter;
121✔
545
            }
546
        }
547

548
        return this->end();
×
549
    }
550

551
    content_line_t get_file_base_content_line(iterator iter)
49✔
552
    {
553
        ssize_t index = std::distance(this->begin(), iter);
49✔
554

555
        return content_line_t(index * MAX_LINES_PER_FILE);
49✔
556
    }
557

558
    void set_index_delegate(index_delegate* id)
633✔
559
    {
560
        if (id != this->lss_index_delegate) {
633✔
561
            this->lss_index_delegate = id;
633✔
562
            this->reload_index_delegate();
633✔
563
        }
564
    }
633✔
565

566
    index_delegate* get_index_delegate() const
567
    {
568
        return this->lss_index_delegate;
569
    }
570

571
    void reload_index_delegate();
572

573
    class meta_grepper
574
        : public grep_proc_source<vis_line_t>
575
        , public grep_proc_sink<vis_line_t> {
576
    public:
577
        meta_grepper(logfile_sub_source& source) : lmg_source(source) {}
1,167✔
578

579
        std::optional<line_info> grep_value_for_line(
580
            vis_line_t line, std::string& value_out) override;
581

582
        vis_line_t grep_initial_line(vis_line_t start,
583
                                     vis_line_t highest) override;
584

585
        void grep_next_line(vis_line_t& line) override;
586

587
        void grep_begin(grep_proc<vis_line_t>& gp,
588
                        vis_line_t start,
589
                        vis_line_t stop) override;
590

591
        void grep_end(grep_proc<vis_line_t>& gp) override;
592

593
        void grep_match(grep_proc<vis_line_t>& gp, vis_line_t line) override;
594

595
        logfile_sub_source& lmg_source;
596
        bool lmg_done{false};
597
    };
598

599
    std::optional<
600
        std::pair<grep_proc_source<vis_line_t>*, grep_proc_sink<vis_line_t>*>>
601
    get_grepper();
602

603
    std::optional<location_history*> get_location_history()
98✔
604
    {
605
        return &this->lss_location_history;
98✔
606
    }
607

608
    void text_crumbs_for_line(int line, std::vector<breadcrumb::crumb>& crumbs);
609

610
    bool text_handle_mouse(textview_curses& tc,
611
                           const listview_curses::display_line_content_t&,
612
                           mouse_event& me);
613

614
    Result<bool, lnav::console::user_message> eval_sql_filter(
615
        sqlite3_stmt* stmt, iterator ld, logfile::const_iterator ll);
616

617
    void invalidate_sql_filter();
618

619
    void set_line_meta_changed() { this->lss_line_meta_changed = true; }
34✔
620

621
    bool is_line_meta_changed() const { return this->lss_line_meta_changed; }
1,605✔
622

623
    void set_exec_context(exec_context* ec) { this->lss_exec_context = ec; }
633✔
624

625
    exec_context* get_exec_context() const { return this->lss_exec_context; }
626

627
    static constexpr uint64_t MAX_CONTENT_LINES = 1ULL << 40;
628
    static constexpr uint64_t MAX_LINES_PER_FILE = 1ULL << 27;
629
    static constexpr uint64_t MAX_FILES
630
        = (MAX_CONTENT_LINES / MAX_LINES_PER_FILE);
631

632
    std::function<void(logfile_sub_source&, file_off_t, file_size_t)>
633
        lss_sorting_observer;
634

635
    uint32_t lss_index_generation{0};
636

637
    void quiesce();
638

639
    struct __attribute__((__packed__)) indexed_content {
640
        enum class level_t : uint8_t {
641
            normal,
642
            warning,
643
            error,
644
        };
645

646
        static level_t level_from_log(const logfile::iterator iter)
13,826✔
647
        {
648
            if (!iter->is_message()) {
13,826✔
649
                return level_t::normal;
2,551✔
650
            }
651
            switch (iter->get_msg_level()) {
11,275✔
652
                case log_level_t::LEVEL_WARNING:
78✔
653
                    return level_t::warning;
78✔
654
                case log_level_t::LEVEL_ERROR:
1,663✔
655
                case log_level_t::LEVEL_FATAL:
656
                case log_level_t::LEVEL_CRITICAL:
657
                    return level_t::error;
1,663✔
658
                default:
9,534✔
659
                    return level_t::normal;
9,534✔
660
            }
661
        }
662

663
        indexed_content() = default;
664

665
        indexed_content(content_line_t cl, const logfile::iterator iter)
13,826✔
666
            : ic_value(cl),
13,826✔
667
              ic_level(lnav::enums::to_underlying(level_from_log(iter)))
13,826✔
668
        {
669
        }
13,826✔
670

671
        content_line_t value() const { return content_line_t(this->ic_value); }
484,993✔
672

673
        level_t level() const { return static_cast<level_t>(this->ic_level); }
17,341✔
674

675
        uint64_t ic_value : 38;
676
        uint8_t ic_level : 2;
677
    };
678

679
    big_array<indexed_content> lss_index;
680

681
    std::optional<vis_line_t> row_for_anchor(const std::string& id);
682

683
    std::optional<vis_line_t> adjacent_anchor(vis_line_t vl, direction dir);
684

685
    std::optional<std::string> anchor_for_row(vis_line_t vl);
686

687
    std::unordered_set<std::string> get_anchors();
688

689
    std::optional<json_string> text_row_details(const textview_curses& tc);
690

691
    void reload_config(error_reporter& reporter);
692

693
    bool is_indexing_in_progress() const
96✔
694
    {
695
        return this->lss_indexing_in_progress;
96✔
696
    }
697

698
    void clear_preview()
1✔
699
    {
700
        text_sub_source::clear_preview();
1✔
701

702
        this->set_preview_sql_filter(nullptr);
1✔
703
    }
1✔
704

705
    void add_commands_for_session(
706
        const std::function<void(const std::string&)>& receiver);
707

708
protected:
709
    void text_accel_display_changed() { this->clear_line_size_cache(); }
1✔
710

711
    logline* text_accel_get_line(vis_line_t vl)
2,274✔
712
    {
713
        return this->find_line(this->at(vl));
2,274✔
714
    }
715

716
private:
717
    static const size_t LINE_SIZE_CACHE_SIZE = 512;
718

719
    void clear_line_size_cache()
1,168✔
720
    {
721
        this->lss_line_size_cache.fill(std::make_pair(0, 0));
1,168✔
722
        this->lss_line_size_cache[0].first = -1;
1,168✔
723
    }
1,168✔
724

725
    bool check_extra_filters(iterator ld, logfile::iterator ll);
726

727
    size_t lss_basename_width = 0;
728
    size_t lss_filename_width = 0;
729
    line_context_t lss_line_context{line_context_t::none};
730
    bool lss_force_rebuild{false};
731
    std::vector<std::unique_ptr<logfile_data>> lss_files;
732
    unsigned int lss_all_timestamp_flags{0};
733

734
    std::vector<uint32_t> lss_filtered_index;
735
    auto_mem<sqlite3_stmt> lss_preview_filter_stmt{sqlite3_finalize};
736

737
    bookmarks<content_line_t>::type lss_user_marks{
738
        bookmarks<content_line_t>::create_array()};
739
    auto_mem<sqlite3_stmt> lss_marker_stmt{sqlite3_finalize};
740
    std::string lss_marker_stmt_text;
741

742
    line_flags_t lss_token_flags{0};
743
    iterator lss_token_file_data;
744
    std::shared_ptr<logfile> lss_token_file;
745
    std::string lss_token_value;
746
    string_attrs_t lss_token_attrs;
747
    lnav::document::metadata lss_token_meta;
748
    int lss_token_meta_line{-1};
749
    int lss_token_meta_size{0};
750
    size_t lss_time_column_size{0};
751
    size_t lss_time_column_padding{0};
752
    logline_value_vector lss_token_values;
753
    int lss_token_shift_start{0};
754
    int lss_token_shift_size{0};
755
    shared_buffer lss_share_manager;
756
    logfile::iterator lss_token_line;
757
    std::array<std::pair<int, size_t>, LINE_SIZE_CACHE_SIZE>
758
        lss_line_size_cache;
759
    log_level_t lss_min_log_level{LEVEL_UNKNOWN};
760
    bool lss_marked_only{false};
761
    index_delegate* lss_index_delegate{nullptr};
762
    size_t lss_longest_line{0};
763
    meta_grepper lss_meta_grepper;
764
    log_location_history lss_location_history;
765
    exec_context* lss_exec_context{nullptr};
766

767
    bool lss_in_value_for_line{false};
768
    bool lss_line_meta_changed{false};
769

770
    bool lss_indexing_in_progress{false};
771
};
772

773
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc