summaryrefslogtreecommitdiffstats
path: root/src/log_vtab_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/log_vtab_impl.cc568
1 files changed, 334 insertions, 234 deletions
diff --git a/src/log_vtab_impl.cc b/src/log_vtab_impl.cc
index 7325675..0f905fc 100644
--- a/src/log_vtab_impl.cc
+++ b/src/log_vtab_impl.cc
@@ -33,7 +33,9 @@
#include "base/itertools.hh"
#include "base/lnav_log.hh"
#include "base/string_util.hh"
+#include "bookmarks.json.hh"
#include "config.h"
+#include "hasher.hh"
#include "lnav_util.hh"
#include "logfile_sub_source.hh"
#include "sql_util.hh"
@@ -53,21 +55,22 @@ static struct log_cursor log_cursor_latest;
thread_local _log_vtab_data log_vtab_data;
static const char* LOG_COLUMNS = R"( (
- log_line INTEGER, -- The line number for the log message
- log_part TEXT COLLATE naturalnocase, -- The partition the message is in
+ log_line INTEGER, -- The line number for the log message
log_time DATETIME, -- The adjusted timestamp for the log message
- log_actual_time DATETIME HIDDEN, -- The timestamp from the original log file for this message
- log_idle_msecs INTEGER, -- The difference in time between this messages and the previous
log_level TEXT COLLATE loglevel, -- The log message level
- log_mark BOOLEAN, -- True if the log message was marked
- log_comment TEXT, -- The comment for this message
- log_tags TEXT, -- A JSON list of tags for this message
- log_filters TEXT, -- A JSON list of filter IDs that matched this message
-- BEGIN Format-specific fields:
)";
static const char* LOG_FOOTER_COLUMNS = R"(
-- END Format-specific fields
+ log_part TEXT COLLATE naturalnocase, -- The partition the message is in
+ log_actual_time DATETIME HIDDEN, -- The timestamp from the original log file for this message
+ log_idle_msecs INTEGER, -- The difference in time between this messages and the previous
+ log_mark BOOLEAN, -- True if the log message was marked
+ log_comment TEXT, -- The comment for this message
+ log_tags TEXT, -- A JSON list of tags for this message
+ log_annotations TEXT, -- A JSON object of annotations for this messages
+ log_filters TEXT, -- A JSON list of filter IDs that matched this message
log_opid TEXT HIDDEN, -- The message's OPID
log_format TEXT HIDDEN, -- The name of the log file format
log_format_regex TEXT HIDDEN, -- The name of the regex used to parse this log message
@@ -81,6 +84,14 @@ static const char* LOG_FOOTER_COLUMNS = R"(
)";
enum class log_footer_columns : uint32_t {
+ partition,
+ actual_time,
+ idle_msecs,
+ mark,
+ comment,
+ tags,
+ annotations,
+ filters,
opid,
format,
format_regex,
@@ -108,8 +119,6 @@ log_vtab_impl::get_table_statement()
max_name_len = std::max(max_name_len, iter->vc_name.length());
}
for (iter = cols.begin(); iter != cols.end(); iter++) {
- auto_mem<char, sqlite3_free> coldecl;
- auto_mem<char, sqlite3_free> colname;
std::string comment;
require(!iter->vc_name.empty());
@@ -118,8 +127,8 @@ log_vtab_impl::get_table_statement()
comment.append(" -- ").append(iter->vc_comment);
}
- colname = sql_quote_ident(iter->vc_name.c_str());
- coldecl = sqlite3_mprintf(
+ auto colname = sql_quote_ident(iter->vc_name.c_str());
+ auto coldecl = lnav::sql::mprintf(
" %-*s %-7s %s COLLATE %-15Q,%s\n",
max_name_len,
colname.in(),
@@ -154,7 +163,7 @@ log_vtab_impl::get_table_statement()
oss << ");\n";
- log_debug("log_vtab_impl.get_table_statement() -> %s", oss.str().c_str());
+ log_trace("log_vtab_impl.get_table_statement() -> %s", oss.str().c_str());
return oss.str();
}
@@ -206,6 +215,7 @@ log_vtab_impl::get_foreign_keys(std::vector<std::string>& keys_inout) const
keys_inout.emplace_back("log_mark");
keys_inout.emplace_back("log_time_msecs");
keys_inout.emplace_back("log_top_line()");
+ keys_inout.emplace_back("log_msg_line()");
}
void
@@ -291,6 +301,12 @@ struct log_vtab {
textview_curses* tc{nullptr};
logfile_sub_source* lss{nullptr};
std::shared_ptr<log_vtab_impl> vi;
+
+ size_t footer_index(log_footer_columns col) const
+ {
+ return VT_COL_MAX + this->vi->vi_column_count
+ + lnav::enums::to_underlying(col);
+ }
};
struct vtab_cursor {
@@ -458,7 +474,8 @@ populate_indexed_columns(vtab_cursor* vc, log_vtab* vt)
vt->vi->extract(lf, line_number, vc->line_values);
}
- int sub_col = ic.cc_column - VT_COL_MAX;
+ auto sub_col = logline_value_meta::table_column{
+ (size_t) (ic.cc_column - VT_COL_MAX)};
auto lv_iter = find_if(vc->line_values.lvv_values.begin(),
vc->line_values.lvv_values.end(),
logline_value_cmp(nullptr, sub_col));
@@ -622,37 +639,6 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
break;
}
- case VT_COL_PARTITION: {
- auto& vb = vt->tc->get_bookmarks();
- const auto& bv = vb[&textview_curses::BM_META];
-
- if (bv.empty()) {
- sqlite3_result_null(ctx);
- } else {
- vis_line_t curr_line(vc->log_cursor.lc_curr_line);
- auto iter = lower_bound(bv.begin(), bv.end(), curr_line + 1_vl);
-
- if (iter != bv.begin()) {
- --iter;
- auto line_meta_opt = vt->lss->find_bookmark_metadata(*iter);
- if (line_meta_opt
- && !line_meta_opt.value()->bm_name.empty())
- {
- sqlite3_result_text(
- ctx,
- line_meta_opt.value()->bm_name.c_str(),
- line_meta_opt.value()->bm_name.size(),
- SQLITE_TRANSIENT);
- } else {
- sqlite3_result_null(ctx);
- }
- } else {
- sqlite3_result_null(ctx);
- }
- }
- break;
- }
-
case VT_COL_LOG_TIME: {
char buffer[64];
@@ -662,63 +648,6 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
break;
}
- case VT_COL_LOG_ACTUAL_TIME: {
- char buffer[64];
-
- if (ll->is_time_skewed()) {
- if (vc->line_values.lvv_values.empty()) {
- vc->cache_msg(lf, ll);
- require(vc->line_values.lvv_sbr.get_data() != nullptr);
- vt->vi->extract(lf, line_number, vc->line_values);
- }
-
- struct line_range time_range;
-
- time_range = find_string_attr_range(vt->vi->vi_attrs,
- &logline::L_TIMESTAMP);
-
- const auto* time_src
- = vc->line_values.lvv_sbr.get_data() + time_range.lr_start;
- struct timeval actual_tv;
- struct exttm tm;
-
- if (lf->get_format()->lf_date_time.scan(
- time_src,
- time_range.length(),
- lf->get_format()->get_timestamp_formats(),
- &tm,
- actual_tv,
- false))
- {
- sql_strftime(buffer, sizeof(buffer), actual_tv);
- }
- } else {
- sql_strftime(
- buffer, sizeof(buffer), ll->get_time(), ll->get_millis());
- }
- sqlite3_result_text(ctx, buffer, strlen(buffer), SQLITE_TRANSIENT);
- break;
- }
-
- case VT_COL_IDLE_MSECS:
- if (vc->log_cursor.lc_curr_line == 0) {
- sqlite3_result_int64(ctx, 0);
- } else {
- content_line_t prev_cl(
- vt->lss->at(vis_line_t(vc->log_cursor.lc_curr_line - 1)));
- auto prev_lf = vt->lss->find(prev_cl);
- auto prev_ll = prev_lf->begin() + prev_cl;
- uint64_t prev_time, curr_line_time;
-
- prev_time = prev_ll->get_time() * 1000ULL;
- prev_time += prev_ll->get_millis();
- curr_line_time = ll->get_time() * 1000ULL;
- curr_line_time += ll->get_millis();
- // require(curr_line_time >= prev_time);
- sqlite3_result_int64(ctx, curr_line_time - prev_time);
- }
- break;
-
case VT_COL_LEVEL: {
const char* level_name = ll->get_level_name();
@@ -727,91 +656,208 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
break;
}
- case VT_COL_MARK: {
- sqlite3_result_int(ctx, ll->is_marked());
- break;
- }
+ default:
+ if (col > (VT_COL_MAX + vt->vi->vi_column_count - 1)) {
+ auto footer_column = static_cast<log_footer_columns>(
+ col - (VT_COL_MAX + vt->vi->vi_column_count - 1) - 1);
- case VT_COL_LOG_COMMENT: {
- auto line_meta_opt
- = vt->lss->find_bookmark_metadata(vc->log_cursor.lc_curr_line);
- if (!line_meta_opt || line_meta_opt.value()->bm_comment.empty()) {
- sqlite3_result_null(ctx);
- } else {
- const auto& meta = *(line_meta_opt.value());
- sqlite3_result_text(ctx,
- meta.bm_comment.c_str(),
- meta.bm_comment.length(),
- SQLITE_TRANSIENT);
- }
- break;
- }
+ switch (footer_column) {
+ case log_footer_columns::partition: {
+ auto& vb = vt->tc->get_bookmarks();
+ const auto& bv = vb[&textview_curses::BM_PARTITION];
- case VT_COL_LOG_TAGS: {
- auto line_meta_opt
- = vt->lss->find_bookmark_metadata(vc->log_cursor.lc_curr_line);
- if (!line_meta_opt || line_meta_opt.value()->bm_tags.empty()) {
- sqlite3_result_null(ctx);
- } else {
- const auto& meta = *(line_meta_opt.value());
+ if (bv.empty()) {
+ sqlite3_result_null(ctx);
+ } else {
+ vis_line_t curr_line(vc->log_cursor.lc_curr_line);
+ auto iter = lower_bound(
+ bv.begin(), bv.end(), curr_line + 1_vl);
+
+ if (iter != bv.begin()) {
+ --iter;
+ auto line_meta_opt
+ = vt->lss->find_bookmark_metadata(*iter);
+ if (line_meta_opt
+ && !line_meta_opt.value()->bm_name.empty())
+ {
+ sqlite3_result_text(
+ ctx,
+ line_meta_opt.value()->bm_name.c_str(),
+ line_meta_opt.value()->bm_name.size(),
+ SQLITE_TRANSIENT);
+ } else {
+ sqlite3_result_null(ctx);
+ }
+ } else {
+ sqlite3_result_null(ctx);
+ }
+ }
+ break;
+ }
+ case log_footer_columns::actual_time: {
+ char buffer[64];
+
+ if (ll->is_time_skewed()) {
+ if (vc->line_values.lvv_values.empty()) {
+ vc->cache_msg(lf, ll);
+ require(vc->line_values.lvv_sbr.get_data()
+ != nullptr);
+ vt->vi->extract(
+ lf, line_number, vc->line_values);
+ }
- yajlpp_gen gen;
+ struct line_range time_range;
- yajl_gen_config(gen, yajl_gen_beautify, false);
+ time_range = find_string_attr_range(
+ vt->vi->vi_attrs, &logline::L_TIMESTAMP);
- {
- yajlpp_array arr(gen);
+ const auto* time_src
+ = vc->line_values.lvv_sbr.get_data()
+ + time_range.lr_start;
+ struct timeval actual_tv;
+ struct exttm tm;
- for (const auto& str : meta.bm_tags) {
- arr.gen(str);
+ if (lf->get_format()->lf_date_time.scan(
+ time_src,
+ time_range.length(),
+ lf->get_format()->get_timestamp_formats(),
+ &tm,
+ actual_tv,
+ false))
+ {
+ sql_strftime(buffer, sizeof(buffer), actual_tv);
+ }
+ } else {
+ sql_strftime(buffer,
+ sizeof(buffer),
+ ll->get_time(),
+ ll->get_millis());
+ }
+ sqlite3_result_text(
+ ctx, buffer, strlen(buffer), SQLITE_TRANSIENT);
+ break;
}
- }
-
- to_sqlite(ctx, json_string(gen));
- }
- break;
- }
+ case log_footer_columns::idle_msecs: {
+ if (vc->log_cursor.lc_curr_line == 0) {
+ sqlite3_result_int64(ctx, 0);
+ } else {
+ content_line_t prev_cl(vt->lss->at(
+ vis_line_t(vc->log_cursor.lc_curr_line - 1)));
+ auto prev_lf = vt->lss->find(prev_cl);
+ auto prev_ll = prev_lf->begin() + prev_cl;
+ uint64_t prev_time, curr_line_time;
+
+ prev_time = prev_ll->get_time() * 1000ULL;
+ prev_time += prev_ll->get_millis();
+ curr_line_time = ll->get_time() * 1000ULL;
+ curr_line_time += ll->get_millis();
+ // require(curr_line_time >= prev_time);
+ sqlite3_result_int64(ctx,
+ curr_line_time - prev_time);
+ }
+ break;
+ }
+ case log_footer_columns::mark: {
+ sqlite3_result_int(ctx, ll->is_marked());
+ break;
+ }
+ case log_footer_columns::comment: {
+ auto line_meta_opt = vt->lss->find_bookmark_metadata(
+ vc->log_cursor.lc_curr_line);
+ if (!line_meta_opt
+ || line_meta_opt.value()->bm_comment.empty())
+ {
+ sqlite3_result_null(ctx);
+ } else {
+ const auto& meta = *(line_meta_opt.value());
+ sqlite3_result_text(ctx,
+ meta.bm_comment.c_str(),
+ meta.bm_comment.length(),
+ SQLITE_TRANSIENT);
+ }
+ break;
+ }
+ case log_footer_columns::tags: {
+ auto line_meta_opt = vt->lss->find_bookmark_metadata(
+ vc->log_cursor.lc_curr_line);
+ if (!line_meta_opt
+ || line_meta_opt.value()->bm_tags.empty())
+ {
+ sqlite3_result_null(ctx);
+ } else {
+ const auto& meta = *(line_meta_opt.value());
- case VT_COL_FILTERS: {
- const auto& filter_mask
- = (*ld)->ld_filter_state.lfo_filter_state.tfs_mask;
+ yajlpp_gen gen;
- if (!filter_mask[line_number]) {
- sqlite3_result_null(ctx);
- } else {
- const auto& filters = vt->lss->get_filters();
- yajlpp_gen gen;
+ yajl_gen_config(gen, yajl_gen_beautify, false);
- yajl_gen_config(gen, yajl_gen_beautify, false);
+ {
+ yajlpp_array arr(gen);
- {
- yajlpp_array arr(gen);
+ for (const auto& str : meta.bm_tags) {
+ arr.gen(str);
+ }
+ }
- for (const auto& filter : filters) {
- if (filter->lf_deleted) {
- continue;
+ to_sqlite(ctx, json_string(gen));
+ }
+ break;
+ }
+ case log_footer_columns::annotations: {
+ if (sqlite3_vtab_nochange(ctx)) {
+ return SQLITE_OK;
}
- uint32_t mask = (1UL << filter->get_index());
-
- if (filter_mask[line_number] & mask) {
- arr.gen(filter->get_index());
+ auto line_meta_opt = vt->lss->find_bookmark_metadata(
+ vc->log_cursor.lc_curr_line);
+ if (!line_meta_opt
+ || line_meta_opt.value()
+ ->bm_annotations.la_pairs.empty())
+ {
+ sqlite3_result_null(ctx);
+ } else {
+ const auto& meta = *(line_meta_opt.value());
+ to_sqlite(
+ ctx,
+ logmsg_annotations_handlers.to_json_string(
+ meta.bm_annotations));
}
+ break;
}
- }
+ case log_footer_columns::filters: {
+ const auto& filter_mask
+ = (*ld)->ld_filter_state.lfo_filter_state.tfs_mask;
- to_sqlite(ctx, gen.to_string_fragment());
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
- }
- break;
- }
+ if (!filter_mask[line_number]) {
+ sqlite3_result_null(ctx);
+ } else {
+ const auto& filters = vt->lss->get_filters();
+ yajlpp_gen gen;
- default:
- if (col > (VT_COL_MAX + vt->vi->vi_column_count - 1)) {
- auto footer_column = static_cast<log_footer_columns>(
- col - (VT_COL_MAX + vt->vi->vi_column_count - 1) - 1);
+ yajl_gen_config(gen, yajl_gen_beautify, false);
- switch (footer_column) {
+ {
+ yajlpp_array arr(gen);
+
+ for (const auto& filter : filters) {
+ if (filter->lf_deleted) {
+ continue;
+ }
+
+ uint32_t mask
+ = (1UL << filter->get_index());
+
+ if (filter_mask[line_number] & mask) {
+ arr.gen(filter->get_index());
+ }
+ }
+ }
+
+ to_sqlite(ctx, gen.to_string_fragment());
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+ }
+ break;
+ }
case log_footer_columns::opid: {
if (vc->line_values.lvv_values.empty()) {
vc->cache_msg(lf, ll);
@@ -820,16 +866,9 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
vt->vi->extract(lf, line_number, vc->line_values);
}
- auto opid_opt = get_string_attr(vt->vi->vi_attrs,
- logline::L_OPID);
- if (opid_opt) {
- auto opid_range
- = opid_opt.value().saw_string_attr->sa_range;
-
- to_sqlite(
- ctx,
- vc->line_values.lvv_sbr.to_string_fragment(
- opid_range.lr_start, opid_range.length()));
+ if (vc->line_values.lvv_opid_value) {
+ to_sqlite(ctx,
+ vc->line_values.lvv_opid_value.value());
} else {
sqlite3_result_null(ctx);
}
@@ -859,15 +898,19 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
case log_footer_columns::path: {
const auto& fn = lf->get_filename();
- sqlite3_result_text(
- ctx, fn.c_str(), fn.length(), SQLITE_STATIC);
+ sqlite3_result_text(ctx,
+ fn.c_str(),
+ fn.native().length(),
+ SQLITE_STATIC);
break;
}
case log_footer_columns::unique_path: {
const auto& fn = lf->get_unique_path();
- sqlite3_result_text(
- ctx, fn.c_str(), fn.length(), SQLITE_STATIC);
+ sqlite3_result_text(ctx,
+ fn.c_str(),
+ fn.native().length(),
+ SQLITE_STATIC);
break;
}
case log_footer_columns::text: {
@@ -958,7 +1001,8 @@ vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
vt->vi->extract(lf, line_number, vc->line_values);
}
- int sub_col = col - VT_COL_MAX;
+ auto sub_col = logline_value_meta::table_column{
+ (size_t) (col - VT_COL_MAX)};
auto lv_iter = find_if(vc->line_values.lvv_values.begin(),
vc->line_values.lvv_values.end(),
logline_value_cmp(nullptr, sub_col));
@@ -1179,7 +1223,7 @@ log_cursor::update(unsigned char op, vis_line_t vl, constraint_t cons)
case SQLITE_INDEX_CONSTRAINT_LE:
if (vl < 0_vl) {
this->lc_curr_line = this->lc_end_line;
- } else {
+ } else if (vl < this->lc_end_line) {
this->lc_end_line
= vl + (cons == constraint_t::unique ? 1_vl : 0_vl);
}
@@ -1187,7 +1231,7 @@ log_cursor::update(unsigned char op, vis_line_t vl, constraint_t cons)
case SQLITE_INDEX_CONSTRAINT_LT:
if (vl <= 0_vl) {
this->lc_curr_line = this->lc_end_line;
- } else {
+ } else if (vl < this->lc_end_line) {
this->lc_end_line = vl;
}
break;
@@ -1250,19 +1294,19 @@ log_cursor::string_constraint::matches(const std::string& sf) const
}
}
-struct time_range {
- nonstd::optional<timeval> tr_begin;
- nonstd::optional<timeval> tr_end;
+struct vtab_time_range {
+ nonstd::optional<timeval> vtr_begin;
+ nonstd::optional<timeval> vtr_end;
- bool empty() const { return !this->tr_begin && !this->tr_end; }
+ bool empty() const { return !this->vtr_begin && !this->vtr_end; }
void add(const timeval& tv)
{
- if (!this->tr_begin || tv < this->tr_begin) {
- this->tr_begin = tv;
+ if (!this->vtr_begin || tv < this->vtr_begin) {
+ this->vtr_begin = tv;
}
- if (!this->tr_end || this->tr_end < tv) {
- this->tr_end = tv;
+ if (!this->vtr_end || this->vtr_end < tv) {
+ this->vtr_end = tv;
}
}
};
@@ -1310,7 +1354,7 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
p_cur->log_cursor.lc_curr_line = 0_vl;
p_cur->log_cursor.lc_end_line = vis_line_t(vt->lss->text_line_count());
- nonstd::optional<time_range> log_time_range;
+ nonstd::optional<vtab_time_range> log_time_range;
nonstd::optional<log_cursor::opid_hash> opid_val;
std::vector<log_cursor::string_constraint> log_path_constraints;
std::vector<log_cursor::string_constraint> log_unique_path_constraints;
@@ -1363,23 +1407,23 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
case SQLITE_INDEX_CONSTRAINT_EQ:
case SQLITE_INDEX_CONSTRAINT_IS:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
log_time_range->add(tv);
break;
case SQLITE_INDEX_CONSTRAINT_GT:
case SQLITE_INDEX_CONSTRAINT_GE:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
- log_time_range->tr_begin = tv;
+ log_time_range->vtr_begin = tv;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
case SQLITE_INDEX_CONSTRAINT_LE:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
- log_time_range->tr_end = tv;
+ log_time_range->vtr_end = tv;
break;
}
}
@@ -1407,23 +1451,23 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
case SQLITE_INDEX_CONSTRAINT_EQ:
case SQLITE_INDEX_CONSTRAINT_IS:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
log_time_range->add(tv);
break;
case SQLITE_INDEX_CONSTRAINT_GT:
case SQLITE_INDEX_CONSTRAINT_GE:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
- log_time_range->tr_begin = tv;
+ log_time_range->vtr_begin = tv;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
case SQLITE_INDEX_CONSTRAINT_LE:
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
- log_time_range->tr_end = tv;
+ log_time_range->vtr_end = tv;
break;
}
break;
@@ -1455,21 +1499,24 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
auto opid = from_sqlite<string_fragment>()(
argc, argv, lpc);
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
for (const auto& file_data : *vt->lss) {
if (file_data->get_file_ptr() == nullptr) {
continue;
}
- safe::ReadAccess<logfile::safe_opid_map>
+ safe::ReadAccess<logfile::safe_opid_state>
r_opid_map(
file_data->get_file_ptr()->get_opids());
- const auto& iter = r_opid_map->find(opid);
- if (iter == r_opid_map->end()) {
+ const auto& iter
+ = r_opid_map->los_opid_ranges.find(opid);
+ if (iter == r_opid_map->los_opid_ranges.end()) {
continue;
}
- log_time_range->add(iter->second.otr_begin);
- log_time_range->add(iter->second.otr_end);
+ log_time_range->add(
+ iter->second.otr_range.tr_begin);
+ log_time_range->add(
+ iter->second.otr_range.tr_end);
}
opid_val = log_cursor::opid_hash{
@@ -1489,7 +1536,7 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
auto found = false;
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
for (const auto& file_data : *vt->lss) {
auto* lf = file_data->get_file_ptr();
@@ -1522,7 +1569,7 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
auto found = false;
if (!log_time_range) {
- log_time_range = time_range{};
+ log_time_range = vtab_time_range{};
}
for (const auto& file_data : *vt->lss) {
auto* lf = file_data->get_file_ptr();
@@ -1545,6 +1592,14 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
}
break;
}
+ case log_footer_columns::partition:
+ case log_footer_columns::actual_time:
+ case log_footer_columns::idle_msecs:
+ case log_footer_columns::mark:
+ case log_footer_columns::comment:
+ case log_footer_columns::tags:
+ case log_footer_columns::annotations:
+ case log_footer_columns::filters:
case log_footer_columns::text:
case log_footer_columns::body:
case log_footer_columns::raw_text:
@@ -1654,25 +1709,25 @@ vt_filter(sqlite3_vtab_cursor* p_vtc,
} else if (log_time_range->empty()) {
p_cur->log_cursor.lc_curr_line = p_cur->log_cursor.lc_end_line;
} else {
- if (log_time_range->tr_begin) {
+ if (log_time_range->vtr_begin) {
auto vl_opt
- = vt->lss->row_for_time(log_time_range->tr_begin.value());
+ = vt->lss->row_for_time(log_time_range->vtr_begin.value());
if (!vl_opt) {
p_cur->log_cursor.lc_curr_line = p_cur->log_cursor.lc_end_line;
} else {
p_cur->log_cursor.lc_curr_line = vl_opt.value();
}
}
- if (log_time_range->tr_end) {
+ if (log_time_range->vtr_end) {
auto vl_max_opt
- = vt->lss->row_for_time(log_time_range->tr_end.value());
+ = vt->lss->row_for_time(log_time_range->vtr_end.value());
if (vl_max_opt) {
p_cur->log_cursor.lc_end_line = vl_max_opt.value();
for (const auto& msg_info :
vt->lss->window_at(vl_max_opt.value(),
vis_line_t(vt->lss->text_line_count())))
{
- if (log_time_range->tr_end.value()
+ if (log_time_range->vtr_end.value()
< msg_info.get_logline().get_timeval())
{
break;
@@ -1829,6 +1884,14 @@ vt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info)
sql_constraint_op_name(op)));
break;
}
+ case log_footer_columns::partition:
+ case log_footer_columns::actual_time:
+ case log_footer_columns::idle_msecs:
+ case log_footer_columns::mark:
+ case log_footer_columns::comment:
+ case log_footer_columns::tags:
+ case log_footer_columns::annotations:
+ case log_footer_columns::filters:
case log_footer_columns::text:
case log_footer_columns::body:
case log_footer_columns::raw_text:
@@ -1911,13 +1974,18 @@ vt_update(sqlite3_vtab* tab,
&& sqlite3_value_int64(argv[0]) == sqlite3_value_int64(argv[1]))
{
int64_t rowid = sqlite3_value_int64(argv[0]) >> 8;
- int val = sqlite3_value_int(argv[2 + VT_COL_MARK]);
+ int val = sqlite3_value_int(
+ argv[2 + vt->footer_index(log_footer_columns::mark)]);
vis_line_t vrowid(rowid);
- const auto* part_name = sqlite3_value_text(argv[2 + VT_COL_PARTITION]);
- const auto* log_comment
- = sqlite3_value_text(argv[2 + VT_COL_LOG_COMMENT]);
- const auto* log_tags = sqlite3_value_text(argv[2 + VT_COL_LOG_TAGS]);
+ const auto* part_name = sqlite3_value_text(
+ argv[2 + vt->footer_index(log_footer_columns::partition)]);
+ const auto* log_comment = sqlite3_value_text(
+ argv[2 + vt->footer_index(log_footer_columns::comment)]);
+ const auto log_tags = from_sqlite<nonstd::optional<string_fragment>>()(
+ argc, argv, 2 + vt->footer_index(log_footer_columns::tags));
+ const auto log_annos = from_sqlite<nonstd::optional<string_fragment>>()(
+ argc, argv, 2 + vt->footer_index(log_footer_columns::annotations));
bookmark_metadata tmp_bm;
if (log_tags) {
@@ -1936,7 +2004,7 @@ vt_update(sqlite3_vtab* tab,
errors.emplace_back(msg);
})
.with_obj(tmp_bm);
- ypc.parse_doc(string_fragment{log_tags});
+ ypc.parse_doc(log_tags.value());
if (!errors.empty()) {
auto top_error = lnav::console::user_message::error(
attr_line_t("invalid value for ")
@@ -1945,30 +2013,53 @@ vt_update(sqlite3_vtab* tab,
.append_quoted(lnav::roles::symbol(
vt->vi->get_name().to_string())))
.with_reason(errors[0].to_attr_line({}));
- auto json_error = lnav::to_json(top_error);
- tab->zErrMsg
- = sqlite3_mprintf("lnav-error:%s", json_error.c_str());
+ set_vtable_errmsg(tab, top_error);
+ return SQLITE_ERROR;
+ }
+ }
+ if (log_annos) {
+ static const intern_string_t SRC
+ = intern_string::lookup("log_annotations");
+
+ auto parse_res = logmsg_annotations_handlers.parser_for(SRC).of(
+ log_annos.value());
+ if (parse_res.isErr()) {
+ set_vtable_errmsg(tab, parse_res.unwrapErr()[0]);
return SQLITE_ERROR;
}
+
+ tmp_bm.bm_annotations = parse_res.unwrap();
}
- auto& bv = vt->tc->get_bookmarks()[&textview_curses::BM_META];
- bool has_meta = part_name != nullptr || log_comment != nullptr
- || log_tags != nullptr;
+ auto& bv_meta = vt->tc->get_bookmarks()[&textview_curses::BM_META];
+ bool has_meta = log_comment != nullptr || log_tags.has_value()
+ || log_annos.has_value();
- if (binary_search(bv.begin(), bv.end(), vrowid) && !has_meta) {
+ if (std::binary_search(bv_meta.begin(), bv_meta.end(), vrowid)
+ && !has_meta)
+ {
vt->tc->set_user_mark(&textview_curses::BM_META, vrowid, false);
- vt->lss->erase_bookmark_metadata(vrowid);
vt->lss->set_line_meta_changed();
}
+ if (!has_meta && part_name == nullptr) {
+ vt->lss->erase_bookmark_metadata(vrowid);
+ }
+
+ if (part_name) {
+ auto& line_meta = vt->lss->get_bookmark_metadata(vrowid);
+ line_meta.bm_name = std::string((const char*) part_name);
+ vt->tc->set_user_mark(&textview_curses::BM_PARTITION, vrowid, true);
+ } else {
+ vt->tc->set_user_mark(
+ &textview_curses::BM_PARTITION, vrowid, false);
+ }
+
if (has_meta) {
auto& line_meta = vt->lss->get_bookmark_metadata(vrowid);
vt->tc->set_user_mark(&textview_curses::BM_META, vrowid, true);
- if (part_name) {
- line_meta.bm_name = std::string((const char*) part_name);
- } else {
+ if (part_name == nullptr) {
line_meta.bm_name.clear();
}
if (log_comment) {
@@ -1988,6 +2079,15 @@ vt_update(sqlite3_vtab* tab,
} else {
line_meta.bm_tags.clear();
}
+ if (log_annos) {
+ line_meta.bm_annotations = std::move(tmp_bm.bm_annotations);
+ } else if (!sqlite3_value_nochange(
+ argv[2
+ + vt->footer_index(
+ log_footer_columns::annotations)]))
+ {
+ line_meta.bm_annotations.la_pairs.clear();
+ }
vt->lss->set_line_meta_changed();
}