summaryrefslogtreecommitdiffstats
path: root/src/session_data.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/session_data.cc719
1 files changed, 428 insertions, 291 deletions
diff --git a/src/session_data.cc b/src/session_data.cc
index 73cb7f8..1b57da4 100644
--- a/src/session_data.cc
+++ b/src/session_data.cc
@@ -34,7 +34,6 @@
#include "session_data.hh"
-#include <fcntl.h>
#include <glob.h>
#include <stdio.h>
#include <sys/types.h>
@@ -44,11 +43,13 @@
#include "base/isc.hh"
#include "base/opt_util.hh"
#include "base/paths.hh"
+#include "bookmarks.json.hh"
+#include "bound_tags.hh"
#include "command_executor.hh"
#include "config.h"
+#include "hasher.hh"
#include "lnav.events.hh"
#include "lnav.hh"
-#include "lnav_util.hh"
#include "log_format_ext.hh"
#include "logfile.hh"
#include "service_tags.hh"
@@ -59,7 +60,8 @@
#include "yajlpp/yajlpp.hh"
#include "yajlpp/yajlpp_def.hh"
-struct session_data_t session_data;
+session_data_t session_data;
+recent_refs_t recent_refs;
static const char* LOG_METADATA_NAME = "log_metadata.db";
@@ -73,6 +75,7 @@ CREATE TABLE IF NOT EXISTS bookmarks (
access_time datetime DEFAULT CURRENT_TIMESTAMP,
comment text DEFAULT '',
tags text DEFAULT '',
+ annotations text DEFAULT NULL,
PRIMARY KEY (log_time, log_format, log_hash, session_time)
);
@@ -125,13 +128,28 @@ static const char* NETLOC_LRU_STMT
static const char* UPGRADE_STMTS[] = {
R"(ALTER TABLE bookmarks ADD COLUMN comment text DEFAULT '';)",
R"(ALTER TABLE bookmarks ADD COLUMN tags text DEFAULT '';)",
+ R"(ALTER TABLE bookmarks ADD COLUMN annotations text DEFAULT NULL;)",
};
static const size_t MAX_SESSIONS = 8;
static const size_t MAX_SESSION_FILE_COUNT = 256;
-static std::vector<content_line_t> marked_session_lines;
-static std::vector<content_line_t> offset_session_lines;
+struct session_line {
+ session_line(struct timeval tv,
+ intern_string_t format_name,
+ std::string line_hash)
+ : sl_time(tv), sl_format_name(format_name),
+ sl_line_hash(std::move(line_hash))
+ {
+ }
+
+ struct timeval sl_time;
+ intern_string_t sl_format_name;
+ std::string sl_line_hash;
+};
+
+static std::vector<session_line> marked_session_lines;
+static std::vector<session_line> offset_session_lines;
static bool
bind_line(sqlite3* db,
@@ -139,7 +157,7 @@ bind_line(sqlite3* db,
content_line_t cl,
time_t session_time)
{
- logfile_sub_source& lss = lnav_data.ld_log_source;
+ auto& lss = lnav_data.ld_log_source;
auto lf = lss.find(cl);
if (lf == nullptr) {
@@ -175,7 +193,9 @@ bind_line(sqlite3* db,
struct session_file_info {
session_file_info(int timestamp, std::string id, std::string path)
: sfi_timestamp(timestamp), sfi_id(std::move(id)),
- sfi_path(std::move(path)){};
+ sfi_path(std::move(path))
+ {
+ }
bool operator<(const session_file_info& other) const
{
@@ -186,7 +206,7 @@ struct session_file_info {
return true;
}
return false;
- };
+ }
int sfi_timestamp;
std::string sfi_id;
@@ -279,6 +299,7 @@ init_session()
{
lnav_data.ld_session_time = time(nullptr);
lnav_data.ld_session_id.clear();
+ session_data.sd_view_states[LNV_LOG].vs_top = -1;
}
static nonstd::optional<std::string>
@@ -294,6 +315,17 @@ compute_session_id()
has_files = true;
h.update(ld_file_name.first);
}
+ for (auto& lf : lnav_data.ld_active_files.fc_files) {
+ if (lf->is_valid_filename()) {
+ continue;
+ }
+ if (!lf->get_open_options().loo_include_in_session) {
+ continue;
+ }
+
+ has_files = true;
+ h.update(lf->get_filename());
+ }
if (!has_files) {
return nonstd::nullopt;
}
@@ -371,6 +403,24 @@ scan_sessions()
void
load_time_bookmarks()
{
+ static const char* BOOKMARK_STMT = R"(
+ SELECT
+ log_time,
+ log_format,
+ log_hash,
+ session_time,
+ part_name,
+ access_time,
+ comment,
+ tags,
+ annotations,
+ session_time=? AS same_session
+ FROM bookmarks WHERE
+ log_time BETWEEN ? AND ? AND
+ log_format = ?
+ ORDER BY same_session DESC, session_time DESC
+)";
+
logfile_sub_source& lss = lnav_data.ld_log_source;
auto_sqlite3 db;
auto db_path = lnav::paths::dotlnav() / LOG_METADATA_NAME;
@@ -412,7 +462,7 @@ load_time_bookmarks()
while (!done) {
done = netloc_stmt.fetch_row<std::string>().match(
[](const std::string& netloc) {
- session_data.sd_recent_netlocs.insert(netloc);
+ recent_refs.rr_netlocs.insert(netloc);
return false;
},
[](const prepared_stmt::fetch_error& fe) {
@@ -424,16 +474,7 @@ load_time_bookmarks()
}
}
- if (sqlite3_prepare_v2(
- db.in(),
- "SELECT log_time, log_format, log_hash, session_time, part_name, "
- "access_time, comment,"
- " tags, session_time=? as same_session FROM bookmarks WHERE "
- " log_time between ? and ? and log_format = ? "
- " ORDER BY same_session DESC, session_time DESC",
- -1,
- stmt.out(),
- nullptr)
+ if (sqlite3_prepare_v2(db.in(), BOOKMARK_STMT, -1, stmt.out(), nullptr)
!= SQLITE_OK)
{
log_error("could not prepare bookmark select statement -- %s",
@@ -446,6 +487,7 @@ load_time_bookmarks()
++file_iter)
{
auto lf = (*file_iter)->get_file();
+ const auto* format = lf->get_format_ptr();
content_line_t base_content_line;
if (lf == nullptr) {
@@ -471,7 +513,6 @@ load_time_bookmarks()
date_time_scanner dts;
bool done = false;
- std::string line;
int64_t last_mark_time = -1;
while (!done) {
@@ -494,6 +535,7 @@ load_time_bookmarks()
= (const char*) sqlite3_column_text(stmt.in(), 6);
const char* tags
= (const char*) sqlite3_column_text(stmt.in(), 7);
+ const auto annotations = sqlite3_column_text(stmt.in(), 8);
int64_t mark_time = sqlite3_column_int64(stmt.in(), 3);
struct timeval log_tv;
struct exttm log_tm;
@@ -509,21 +551,29 @@ load_time_bookmarks()
continue;
}
- if (!dts.scan(
- log_time, strlen(log_time), NULL, &log_tm, log_tv))
+ if (dts.scan(log_time,
+ strlen(log_time),
+ nullptr,
+ &log_tm,
+ log_tv)
+ == nullptr)
{
+ log_warning("bad log time: %s", log_time);
continue;
}
- auto line_iter
- = lower_bound(lf->begin(), lf->end(), log_tv);
+ auto line_iter = format->lf_time_ordered
+ ? std::lower_bound(lf->begin(), lf->end(), log_tv)
+ : lf->begin();
while (line_iter != lf->end()) {
- struct timeval line_tv = line_iter->get_timeval();
+ const auto line_tv = line_iter->get_timeval();
- if ((line_tv.tv_sec != log_tv.tv_sec)
- || (line_tv.tv_usec != log_tv.tv_usec))
- {
- break;
+ if (line_tv != log_tv) {
+ if (format->lf_time_ordered) {
+ break;
+ }
+ ++line_iter;
+ continue;
}
auto cl = content_line_t(
@@ -542,65 +592,93 @@ load_time_bookmarks()
.update(cl)
.to_string();
- if (line_hash == log_hash) {
- auto& bm_meta = lf->get_bookmark_metadata();
- auto line_number = static_cast<uint32_t>(
- std::distance(lf->begin(), line_iter));
- content_line_t line_cl = content_line_t(
- base_content_line + line_number);
- bool meta = false;
-
- if (part_name != nullptr && part_name[0] != '\0') {
- lss.set_user_mark(&textview_curses::BM_META,
- line_cl);
- bm_meta[line_number].bm_name = part_name;
- meta = true;
- }
- if (comment != nullptr && comment[0] != '\0') {
+ if (line_hash != log_hash) {
+ ++line_iter;
+ continue;
+ }
+ auto& bm_meta = lf->get_bookmark_metadata();
+ auto line_number = static_cast<uint32_t>(
+ std::distance(lf->begin(), line_iter));
+ content_line_t line_cl
+ = content_line_t(base_content_line + line_number);
+ bool meta = false;
+
+ if (part_name != nullptr && part_name[0] != '\0') {
+ lss.set_user_mark(&textview_curses::BM_PARTITION,
+ line_cl);
+ bm_meta[line_number].bm_name = part_name;
+ meta = true;
+ }
+ if (comment != nullptr && comment[0] != '\0') {
+ lss.set_user_mark(&textview_curses::BM_META,
+ line_cl);
+ bm_meta[line_number].bm_comment = comment;
+ meta = true;
+ }
+ if (tags != nullptr && tags[0] != '\0') {
+ auto_mem<yajl_val_s> tag_list(yajl_tree_free);
+ char error_buffer[1024];
+
+ tag_list = yajl_tree_parse(
+ tags, error_buffer, sizeof(error_buffer));
+ if (!YAJL_IS_ARRAY(tag_list.in())) {
+ log_error("invalid tags column: %s", tags);
+ } else {
lss.set_user_mark(&textview_curses::BM_META,
line_cl);
- bm_meta[line_number].bm_comment = comment;
- meta = true;
- }
- if (tags != nullptr && tags[0] != '\0') {
- auto_mem<yajl_val_s> tag_list(yajl_tree_free);
- char error_buffer[1024];
-
- tag_list = yajl_tree_parse(
- tags, error_buffer, sizeof(error_buffer));
- if (!YAJL_IS_ARRAY(tag_list.in())) {
- log_error("invalid tags column: %s", tags);
- } else {
- lss.set_user_mark(&textview_curses::BM_META,
- line_cl);
- for (size_t lpc = 0;
- lpc < tag_list.in()->u.array.len;
- lpc++)
- {
- yajl_val elem
- = tag_list.in()
- ->u.array.values[lpc];
-
- if (!YAJL_IS_STRING(elem)) {
- continue;
- }
- bookmark_metadata::KNOWN_TAGS.insert(
- elem->u.string);
- bm_meta[line_number].add_tag(
- elem->u.string);
+ for (size_t lpc = 0;
+ lpc < tag_list.in()->u.array.len;
+ lpc++)
+ {
+ yajl_val elem
+ = tag_list.in()->u.array.values[lpc];
+
+ if (!YAJL_IS_STRING(elem)) {
+ continue;
}
+ bookmark_metadata::KNOWN_TAGS.insert(
+ elem->u.string);
+ bm_meta[line_number].add_tag(
+ elem->u.string);
}
- meta = true;
}
- if (!meta) {
- marked_session_lines.push_back(line_cl);
- lss.set_user_mark(&textview_curses::BM_USER,
+ meta = true;
+ }
+ if (annotations != nullptr && annotations[0] != '\0') {
+ static const intern_string_t SRC
+ = intern_string::lookup("annotations");
+
+ const auto anno_sf
+ = string_fragment::from_c_str(annotations);
+ auto parse_res
+ = logmsg_annotations_handlers.parser_for(SRC)
+ .of(anno_sf);
+ if (parse_res.isErr()) {
+ log_error(
+ "unable to parse annotations JSON -- "
+ "%s",
+ parse_res.unwrapErr()[0]
+ .to_attr_line()
+ .get_string()
+ .c_str());
+ } else {
+ lss.set_user_mark(&textview_curses::BM_META,
line_cl);
+ bm_meta[line_number].bm_annotations
+ = parse_res.unwrap();
+ meta = true;
}
- reload_needed = true;
}
-
- ++line_iter;
+ if (!meta) {
+ marked_session_lines.emplace_back(
+ lf->original_line_time(line_iter),
+ format->get_name(),
+ line_hash);
+ lss.set_user_mark(&textview_curses::BM_USER,
+ line_cl);
+ }
+ reload_needed = true;
+ break;
}
break;
}
@@ -719,11 +797,12 @@ load_time_bookmarks()
if (lf->get_content_id() == log_hash) {
int file_line
= std::distance(lf->begin(), line_iter);
- content_line_t line_cl
- = content_line_t(base_content_line + file_line);
struct timeval offset;
- offset_session_lines.push_back(line_cl);
+ offset_session_lines.emplace_back(
+ lf->original_line_time(line_iter),
+ lf->get_format_ptr()->get_name(),
+ log_hash);
offset.tv_sec = sqlite3_column_int64(stmt.in(), 4);
offset.tv_usec = sqlite3_column_int64(stmt.in(), 5);
lf->adjust_content_time(file_line, offset);
@@ -761,136 +840,32 @@ read_files(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
return 1;
}
-static int
-read_current_search(yajlpp_parse_context* ypc,
- const unsigned char* str,
- size_t len)
-{
- const auto regex = std::string((const char*) str, len);
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-2));
- view_index = view_name - lnav_view_strings;
-
- if (view_index < LNV__MAX && !regex.empty()) {
- lnav_data.ld_views[view_index].execute_search(regex);
- lnav_data.ld_views[view_index].set_follow_search_for(-1, {});
- }
-
- return 1;
-}
-
-static int
-read_top_line(yajlpp_parse_context* ypc, long long value)
-{
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-2));
- view_index = view_name - lnav_view_strings;
- if (view_index < LNV__MAX) {
- session_data.sd_view_states[view_index].vs_top = value;
- }
-
- return 1;
-}
-
-static int
-read_focused_line(yajlpp_parse_context* ypc, long long value)
-{
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-2));
- view_index = view_name - lnav_view_strings;
- if (view_index < LNV__MAX) {
- session_data.sd_view_states[view_index].vs_selection = value;
- }
-
- return 1;
-}
-
-static int
-read_word_wrap(yajlpp_parse_context* ypc, int value)
-{
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-2));
- view_index = view_name - lnav_view_strings;
- if (view_index == LNV_HELP) {
- } else if (view_index < LNV__MAX) {
- textview_curses& tc = lnav_data.ld_views[view_index];
-
- tc.set_word_wrap(value);
- }
-
- return 1;
-}
-
-static int
-read_filtering(yajlpp_parse_context* ypc, int value)
-{
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-2));
- view_index = view_name - lnav_view_strings;
- if (view_index == LNV_HELP) {
- } else if (view_index < LNV__MAX) {
- textview_curses& tc = lnav_data.ld_views[view_index];
-
- if (tc.get_sub_source() != nullptr) {
- tc.get_sub_source()->tss_apply_filters = value;
- }
- }
-
- return 1;
-}
-
-static int
-read_commands(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
-{
- std::string cmdline = std::string((const char*) str, len);
- const char** view_name;
- int view_index;
-
- view_name = find(lnav_view_strings,
- lnav_view_strings + LNV__MAX,
- ypc->get_path_fragment(-3));
- view_index = view_name - lnav_view_strings;
- bool active = ensure_view(&lnav_data.ld_views[view_index]);
- execute_command(lnav_data.ld_exec_context, cmdline);
- if (!active) {
- lnav_data.ld_view_stack.pop_back();
- }
-
- return 1;
-}
-
static const struct json_path_container view_def_handlers = {
- json_path_handler("top_line", read_top_line),
- json_path_handler("focused_line", read_focused_line),
- json_path_handler("search", read_current_search),
- json_path_handler("word_wrap", read_word_wrap),
- json_path_handler("filtering", read_filtering),
- json_path_handler("commands#", read_commands),
+ json_path_handler("top_line").for_field(&view_state::vs_top),
+ json_path_handler("focused_line").for_field(&view_state::vs_selection),
+ json_path_handler("search").for_field(&view_state::vs_search),
+ json_path_handler("word_wrap").for_field(&view_state::vs_word_wrap),
+ json_path_handler("filtering").for_field(&view_state::vs_filtering),
+ json_path_handler("commands#").for_field(&view_state::vs_commands),
};
static const struct json_path_container view_handlers = {
- yajlpp::pattern_property_handler("([^/]+)").with_children(
- view_def_handlers),
+ yajlpp::pattern_property_handler("(?<view_name>[\\w\\-]+)")
+ .with_obj_provider<view_state, session_data_t>(
+ +[](const yajlpp_provider_context& ypc, session_data_t* root) {
+ const char** view_name;
+ int view_index;
+
+ view_name = find(lnav_view_strings,
+ lnav_view_strings + LNV__MAX,
+ ypc.get_substr("view_name"));
+ view_index = view_name - lnav_view_strings;
+ if (view_index < LNV__MAX) {
+ return &root->sd_view_states[view_index];
+ }
+ return (view_state*) nullptr;
+ })
+ .with_children(view_def_handlers),
};
static const struct json_path_container file_state_handlers = {
@@ -902,14 +877,15 @@ static const struct json_path_container file_state_handlers = {
static const struct json_path_container file_states_handlers = {
yajlpp::pattern_property_handler(R"((?<filename>[^/]+))")
.with_description("Map of file names to file state objects")
- .with_obj_provider<file_state, void>([](const auto& ypc, auto* root) {
- auto fn = ypc.get_substr("filename");
- return &session_data.sd_file_states[fn];
- })
+ .with_obj_provider<file_state, session_data_t>(
+ [](const auto& ypc, session_data_t* root) {
+ auto fn = ypc.get_substr("filename");
+ return &root->sd_file_states[fn];
+ })
.with_children(file_state_handlers),
};
-static const struct json_path_container view_info_handlers = {
+static const typed_json_path_container<session_data_t> view_info_handlers = {
yajlpp::property_handler("save-time")
.for_field(&session_data_t::sd_save_time),
yajlpp::property_handler("time-offset")
@@ -922,35 +898,54 @@ static const struct json_path_container view_info_handlers = {
void
load_session()
{
+ log_info("BEGIN load_session");
load_time_bookmarks();
scan_sessions() | [](const auto pair) {
- yajl_handle handle;
- auto_fd fd;
-
lnav_data.ld_session_load_time = pair.first.second;
- session_data.sd_save_time = pair.first.second;
const auto& view_info_path = pair.second;
-
- yajlpp_parse_context ypc(intern_string::lookup(view_info_path.string()),
- &view_info_handlers);
- ypc.with_obj(session_data);
- handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
+ auto view_info_src = intern_string::lookup(view_info_path.string());
load_time_bookmarks();
- if ((fd = lnav::filesystem::openp(view_info_path, O_RDONLY)) < 0) {
- perror("cannot open session file");
- } else {
- unsigned char buffer[1024];
- ssize_t rc;
+ auto open_res = lnav::filesystem::open_file(view_info_path, O_RDONLY);
+ if (open_res.isErr()) {
+ log_error("cannot open session file: %s -- %s",
+ view_info_path.c_str(),
+ open_res.unwrapErr().c_str());
+ return;
+ }
- log_info("loading session file: %s", view_info_path.c_str());
- while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
- yajl_parse(handle, buffer, rc);
+ auto fd = open_res.unwrap();
+ unsigned char buffer[1024];
+ ssize_t rc;
+
+ log_info("loading session file: %s", view_info_path.c_str());
+ auto parser = view_info_handlers.parser_for(view_info_src);
+ while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
+ auto buf_frag = string_fragment::from_bytes(buffer, rc);
+ auto parse_res = parser.consume(buf_frag);
+ if (parse_res.isErr()) {
+ log_error("failed to load session: %s -- %s",
+ view_info_path.c_str(),
+ parse_res.unwrapErr()[0]
+ .to_attr_line()
+ .get_string()
+ .c_str());
+ return;
}
- yajl_complete_parse(handle);
}
- yajl_free(handle);
+
+ auto complete_res = parser.complete();
+ if (complete_res.isErr()) {
+ log_error("failed to load session: %s -- %s",
+ view_info_path.c_str(),
+ complete_res.unwrapErr()[0]
+ .to_attr_line()
+ .get_string()
+ .c_str());
+ return;
+ }
+ session_data = complete_res.unwrap();
bool log_changes = false, text_changes = false;
@@ -964,16 +959,15 @@ load_session()
log_debug("found state for file: %s %d",
lf->get_content_id().c_str(),
iter->second.fs_is_visible);
- lnav_data.ld_log_source.find_data(lf) | [iter](auto ld) {
- ld->set_visibility(iter->second.fs_is_visible);
- };
- if (!iter->second.fs_is_visible) {
- if (lf->get_format() != nullptr) {
- log_changes = true;
- } else {
- text_changes = true;
- }
- }
+ lnav_data.ld_log_source.find_data(lf) |
+ [iter, &log_changes](auto ld) {
+ if (ld->ld_visible != iter->second.fs_is_visible) {
+ ld->get_file_ptr()->set_indexing(
+ iter->second.fs_is_visible);
+ ld->set_visibility(iter->second.fs_is_visible);
+ log_changes = true;
+ }
+ };
}
if (log_changes) {
@@ -986,6 +980,8 @@ load_session()
lnav::events::publish(lnav_data.ld_db.in(),
lnav::events::session::loaded{});
+
+ log_info("END load_session");
}
static void
@@ -1001,13 +997,41 @@ save_user_bookmarks(sqlite3* db,
sqlite3_stmt* stmt,
bookmark_vector<content_line_t>& user_marks)
{
- logfile_sub_source& lss = lnav_data.ld_log_source;
- bookmark_vector<content_line_t>::iterator iter;
+ auto& lss = lnav_data.ld_log_source;
- for (iter = user_marks.begin(); iter != user_marks.end(); ++iter) {
+ for (auto iter = user_marks.begin(); iter != user_marks.end(); ++iter) {
content_line_t cl = *iter;
auto line_meta_opt = lss.find_bookmark_metadata(cl);
- if (!bind_line(db, stmt, cl, lnav_data.ld_session_time)) {
+ auto lf = lss.find(cl);
+ if (lf == nullptr) {
+ continue;
+ }
+
+ sqlite3_clear_bindings(stmt);
+
+ auto line_iter = lf->begin() + cl;
+ auto read_result = lf->read_line(line_iter);
+
+ if (read_result.isErr()) {
+ continue;
+ }
+
+ auto line_hash = read_result
+ .map([cl](auto sbr) {
+ return hasher()
+ .update(sbr.get_data(), sbr.length())
+ .update(cl)
+ .to_string();
+ })
+ .unwrap();
+
+ if (bind_values(stmt,
+ lf->original_line_time(line_iter),
+ lf->get_format()->get_name(),
+ line_hash,
+ lnav_data.ld_session_time)
+ != SQLITE_OK)
+ {
continue;
}
@@ -1019,8 +1043,8 @@ save_user_bookmarks(sqlite3* db,
return;
}
} else {
- bookmark_metadata& line_meta = *(line_meta_opt.value());
- if (line_meta.empty()) {
+ const auto& line_meta = *(line_meta_opt.value());
+ if (line_meta.empty(bookmark_metadata::categories::any)) {
continue;
}
@@ -1071,6 +1095,25 @@ save_user_bookmarks(sqlite3* db,
log_error("could not bind tags -- %s", sqlite3_errmsg(db));
return;
}
+
+ if (!line_meta.bm_annotations.la_pairs.empty()) {
+ auto anno_str = logmsg_annotations_handlers.to_string(
+ line_meta.bm_annotations);
+
+ if (sqlite3_bind_text(stmt,
+ 8,
+ anno_str.c_str(),
+ anno_str.length(),
+ SQLITE_TRANSIENT)
+ != SQLITE_OK)
+ {
+ log_error("could not bind annotations -- %s",
+ sqlite3_errmsg(db));
+ return;
+ }
+ } else {
+ sqlite3_bind_null(stmt, 8);
+ }
}
if (sqlite3_step(stmt) != SQLITE_DONE) {
@@ -1079,7 +1122,9 @@ save_user_bookmarks(sqlite3* db,
return;
}
- marked_session_lines.push_back(cl);
+ marked_session_lines.emplace_back(lf->original_line_time(line_iter),
+ lf->get_format_ptr()->get_name(),
+ line_hash);
sqlite3_reset(stmt);
}
@@ -1142,7 +1187,7 @@ save_time_bookmarks()
sqlite3_reset(stmt.in());
}
- session_data.sd_recent_netlocs.insert(netlocs.begin(), netlocs.end());
+ recent_refs.rr_netlocs.insert(netlocs.begin(), netlocs.end());
}
logfile_sub_source& lss = lnav_data.ld_log_source;
@@ -1163,10 +1208,14 @@ save_time_bookmarks()
}
for (auto& marked_session_line : marked_session_lines) {
- if (!bind_line(db.in(),
- stmt.in(),
- marked_session_line,
- lnav_data.ld_session_time))
+ sqlite3_clear_bindings(stmt.in());
+
+ if (bind_values(stmt,
+ marked_session_line.sl_time,
+ marked_session_line.sl_format_name,
+ marked_session_line.sl_line_hash,
+ lnav_data.ld_session_time)
+ != SQLITE_OK)
{
continue;
}
@@ -1185,8 +1234,8 @@ save_time_bookmarks()
if (sqlite3_prepare_v2(db.in(),
"REPLACE INTO bookmarks"
" (log_time, log_format, log_hash, session_time, "
- "part_name, comment, tags)"
- " VALUES (?, ?, ?, ?, ?, ?, ?)",
+ "part_name, comment, tags, annotations)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
-1,
stmt.out(),
nullptr)
@@ -1240,7 +1289,11 @@ save_time_bookmarks()
}
save_user_bookmarks(db.in(), stmt.in(), bm[&textview_curses::BM_USER]);
- save_user_bookmarks(db.in(), stmt.in(), bm[&textview_curses::BM_META]);
+ auto all_meta_marks = bm[&textview_curses::BM_META];
+ const auto& bm_parts = bm[&textview_curses::BM_PARTITION];
+ all_meta_marks.insert(
+ all_meta_marks.end(), bm_parts.begin(), bm_parts.end());
+ save_user_bookmarks(db.in(), stmt.in(), all_meta_marks);
if (sqlite3_prepare_v2(db.in(),
"DELETE FROM time_offset WHERE "
@@ -1257,10 +1310,14 @@ save_time_bookmarks()
}
for (auto& offset_session_line : offset_session_lines) {
- if (!bind_line(db.in(),
- stmt.in(),
- offset_session_line,
- lnav_data.ld_session_time))
+ sqlite3_clear_bindings(stmt.in());
+
+ if (bind_values(stmt,
+ offset_session_line.sl_time,
+ offset_session_line.sl_format_name,
+ offset_session_line.sl_line_hash,
+ lnav_data.ld_session_time)
+ != SQLITE_OK)
{
continue;
}
@@ -1452,7 +1509,7 @@ save_session_with_id(const std::string& session_id)
for (auto& lf : lnav_data.ld_active_files.fc_files) {
auto ld_opt = lnav_data.ld_log_source.find_data(lf);
- file_states.gen(lf->get_filename());
+ file_states.gen(lf->get_filename().native());
{
yajlpp_map file_state(handle);
@@ -1469,7 +1526,7 @@ save_session_with_id(const std::string& session_id)
yajlpp_map top_view_map(handle);
for (int lpc = 0; lpc < LNV__MAX; lpc++) {
- textview_curses& tc = lnav_data.ld_views[lpc];
+ auto& tc = lnav_data.ld_views[lpc];
unsigned long width;
vis_line_t height;
@@ -1540,47 +1597,44 @@ save_session_with_id(const std::string& session_id)
for (const auto& format :
log_format::get_root_formats())
{
- auto* elf = dynamic_cast<external_log_format*>(
- format.get());
-
- if (elf == nullptr) {
- continue;
- }
+ auto field_states = format->get_field_states();
- for (const auto& vd : elf->elf_value_defs) {
- if (!vd.second->vd_meta.lvm_user_hidden) {
+ for (const auto& fs_pair : field_states) {
+ if (!fs_pair.second.lvm_user_hidden) {
continue;
}
- if (vd.second->vd_meta.lvm_user_hidden.value())
- {
- cmd_array.gen("hide-fields "
- + elf->get_name().to_string()
- + "." + vd.first.to_string());
- } else if (vd.second->vd_meta.lvm_hidden) {
- cmd_array.gen("show-fields "
- + elf->get_name().to_string()
- + "." + vd.first.to_string());
+ if (fs_pair.second.lvm_user_hidden.value()) {
+ cmd_array.gen(
+ "hide-fields "
+ + format->get_name().to_string() + "."
+ + fs_pair.first.to_string());
+ } else if (fs_pair.second.lvm_hidden) {
+ cmd_array.gen(
+ "show-fields "
+ + format->get_name().to_string() + "."
+ + fs_pair.first.to_string());
}
}
}
- logfile_sub_source& lss = lnav_data.ld_log_source;
+ auto& lss = lnav_data.ld_log_source;
- struct timeval min_time, max_time;
- bool have_min_time = lss.get_min_log_time(min_time);
- bool have_max_time = lss.get_max_log_time(max_time);
+ auto min_time_opt = lss.get_min_log_time();
+ auto max_time_opt = lss.get_max_log_time();
char min_time_str[32], max_time_str[32];
- sql_strftime(
- min_time_str, sizeof(min_time_str), min_time);
- if (have_min_time) {
+ if (min_time_opt) {
+ sql_strftime(min_time_str,
+ sizeof(min_time_str),
+ min_time_opt.value());
cmd_array.gen("hide-lines-before "
+ std::string(min_time_str));
}
- if (have_max_time) {
- sql_strftime(
- max_time_str, sizeof(max_time_str), max_time);
+ if (max_time_opt) {
+ sql_strftime(max_time_str,
+ sizeof(max_time_str),
+ max_time_opt.value());
cmd_array.gen("hide-lines-after "
+ std::string(max_time_str));
}
@@ -1701,6 +1755,89 @@ reset_session()
}
void
+lnav::session::restore_view_states()
+{
+ log_debug("restoring view states");
+ for (size_t view_index = 0; view_index < LNV__MAX; view_index++) {
+ const auto& vs = session_data.sd_view_states[view_index];
+ auto& tview = lnav_data.ld_views[view_index];
+ bool has_loc = false;
+
+ if (view_index == LNV_TEXT) {
+ auto lf = lnav_data.ld_text_source.current_file();
+ if (lf != nullptr) {
+ has_loc = lf->get_open_options().loo_init_location.valid();
+ if (!has_loc) {
+ switch (lf->get_text_format()) {
+ case text_format_t::TF_UNKNOWN:
+ case text_format_t::TF_LOG:
+ break;
+ default:
+ if (vs.vs_top == 0 && tview.get_top() > 0) {
+ log_debug("setting to 0");
+ tview.set_top(0_vl);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (!has_loc && vs.vs_top >= 0
+ && (view_index == LNV_LOG || tview.get_top() == 0_vl
+ || tview.get_top() == tview.get_top_for_last_row()))
+ {
+ log_info("restoring %s view top: %d",
+ lnav_view_strings[view_index],
+ vs.vs_top);
+ lnav_data.ld_views[view_index].set_top(vis_line_t(vs.vs_top), true);
+ lnav_data.ld_views[view_index].set_selection(-1_vl);
+ }
+ if (!has_loc && vs.vs_selection) {
+ log_info("restoring %s view selection: %d",
+ lnav_view_strings[view_index],
+ vs.vs_selection.value());
+ lnav_data.ld_views[view_index].set_selection(
+ vis_line_t(vs.vs_selection.value()));
+ }
+
+ if (!vs.vs_search.empty()) {
+ tview.execute_search(vs.vs_search);
+ tview.set_follow_search_for(-1, {});
+ }
+ tview.set_word_wrap(vs.vs_word_wrap);
+ if (tview.get_sub_source() != nullptr) {
+ tview.get_sub_source()->tss_apply_filters = vs.vs_filtering;
+ }
+ for (const auto& cmdline : vs.vs_commands) {
+ auto active = ensure_view(&tview);
+ auto exec_cmd_res
+ = execute_command(lnav_data.ld_exec_context, cmdline);
+ if (exec_cmd_res.isOk()) {
+ log_info("Result: %s", exec_cmd_res.unwrap().c_str());
+ } else {
+ log_error("Result: %s",
+ exec_cmd_res.unwrapErr()
+ .to_attr_line()
+ .get_string()
+ .c_str());
+ }
+ if (!active) {
+ lnav_data.ld_view_stack.pop_back();
+ lnav_data.ld_view_stack.top() | [](auto* tc) {
+ // XXX
+ if (tc == &lnav_data.ld_views[LNV_GANTT]) {
+ auto tss = tc->get_sub_source();
+ tss->text_filters_changed();
+ tc->reload_data();
+ }
+ };
+ }
+ }
+ }
+}
+
+void
lnav::session::regex101::insert_entry(const lnav::session::regex101::entry& ei)
{
constexpr const char* STMT = R"(