mirror of
https://github.com/tstack/lnav
synced 2024-11-01 21:40:34 +00:00
[sql] add a bookmark column to the log tables
This commit is contained in:
parent
7bcbd000ad
commit
10eb9617b1
3
NEWS
3
NEWS
@ -16,6 +16,9 @@ lnav v0.6.3:
|
||||
displayed can be tab-completed.
|
||||
* The '-H' option was added so you can view the internal help text.
|
||||
* Added the 'g/G' hotkeys to move to the top/bottom of the file.
|
||||
* Added a 'log_mark' column to the log tables that indicates whether or
|
||||
not a log message is bookmarked. The field is writable, so you can
|
||||
bookmark lines using an SQL UPDATE query.
|
||||
|
||||
Fixes:
|
||||
* Performance improvements.
|
||||
|
@ -458,6 +458,8 @@ All log tables contain at least the following columns:
|
||||
log_idle_msecs The amount of time, in milliseconds, between the
|
||||
current log message and the previous one.
|
||||
log_level The log level (e.g. info, error, etc...).
|
||||
log_mark The bookmark status for the line. This column
|
||||
can be written to using an UPDATE query.
|
||||
log_path The full path to the file.
|
||||
log_text The raw line of text. Note that this column is
|
||||
not included in the result of a 'select *', but
|
||||
|
@ -1891,13 +1891,6 @@ static void handle_paging_key(int ch)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
if (tc == &lnav_data.ld_views[LNV_LOG]) {
|
||||
lnav_data.ld_log_source.toggle_user_mark(&BM_EXAMPLE,
|
||||
vis_line_t(tc->get_top()));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
execute_command("close");
|
||||
break;
|
||||
|
@ -103,7 +103,7 @@ void ensure_dotlnav(void)
|
||||
path += "/*";
|
||||
if (glob(path.c_str(), GLOB_NOCHECK, NULL, gl.inout()) == 0) {
|
||||
for (int lpc = 0;
|
||||
lpc < (gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
||||
lpc < ((int)gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
||||
lpc++) {
|
||||
remove(gl->gl_pathv[lpc]);
|
||||
}
|
||||
|
@ -119,11 +119,11 @@ public:
|
||||
|
||||
LEVEL__MAX,
|
||||
|
||||
LEVEL_MULTILINE = 0x40, /*< Start of a multiline entry. */
|
||||
LEVEL_MARK = 0x40, /*< Bookmarked line. */
|
||||
LEVEL_CONTINUED = 0x80, /*< Continuation of multiline entry. */
|
||||
|
||||
/** Mask of flags for the level field. */
|
||||
LEVEL__FLAGS = (LEVEL_MULTILINE | LEVEL_CONTINUED)
|
||||
LEVEL__FLAGS = (LEVEL_MARK | LEVEL_CONTINUED)
|
||||
} level_t;
|
||||
|
||||
static const char *level_names[LEVEL__MAX];
|
||||
@ -198,7 +198,16 @@ public:
|
||||
this->ll_millis = tv.tv_usec / 1000;
|
||||
};
|
||||
|
||||
void set_multiline(void) { this->ll_level |= LEVEL_MULTILINE; };
|
||||
void set_mark(bool val) {
|
||||
if (val) {
|
||||
this->ll_level |= LEVEL_MARK;
|
||||
}
|
||||
else {
|
||||
this->ll_level &= ~LEVEL_MARK;
|
||||
}
|
||||
};
|
||||
|
||||
bool is_marked(void) const { return this->ll_level & LEVEL_MARK; };
|
||||
|
||||
/** @param l The logging level. */
|
||||
void set_level(level_t l) { this->ll_level = l; };
|
||||
|
@ -69,7 +69,8 @@ std::string log_vtab_impl::get_table_statement(void)
|
||||
<< " log_part text collate naturalnocase,\n"
|
||||
<< " log_time datetime,\n"
|
||||
<< " log_idle_msecs int,\n"
|
||||
<< " log_level text collate loglevel,\n";
|
||||
<< " log_level text collate loglevel,\n"
|
||||
<< " log_mark boolean,\n";
|
||||
this->get_columns(cols);
|
||||
this->vi_column_count = cols.size();
|
||||
for (iter = cols.begin(); iter != cols.end(); iter++) {
|
||||
@ -328,6 +329,12 @@ static int 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)) {
|
||||
int post_col_number = col -
|
||||
@ -430,6 +437,27 @@ static int vt_best_index(sqlite3_vtab *tab, sqlite3_index_info *p_info)
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int vt_update(sqlite3_vtab *tab,
|
||||
int argc,
|
||||
sqlite3_value **argv,
|
||||
sqlite_int64 *rowid)
|
||||
{
|
||||
vtab *vt = (vtab *)tab;
|
||||
int retval = SQLITE_READONLY;
|
||||
|
||||
if (argc > 1 && sqlite3_value_type(argv[0]) != SQLITE_NULL &&
|
||||
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]);
|
||||
|
||||
vt->tc->set_user_mark(&textview_curses::BM_USER, vis_line_t(rowid), val);
|
||||
|
||||
retval = SQLITE_OK;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static sqlite3_module vtab_module = {
|
||||
0, /* iVersion */
|
||||
vt_create, /* xCreate - create a vtable */
|
||||
@ -444,7 +472,7 @@ static sqlite3_module vtab_module = {
|
||||
vt_eof, /* xEof - inidicate end of result set*/
|
||||
vt_column, /* xColumn - read data */
|
||||
vt_rowid, /* xRowid - read data */
|
||||
NULL, /* xUpdate - write data */
|
||||
vt_update, /* xUpdate - write data */
|
||||
NULL, /* xBegin - begin transaction */
|
||||
NULL, /* xSync - sync transaction */
|
||||
NULL, /* xCommit - commit transaction */
|
||||
|
@ -45,6 +45,7 @@ enum {
|
||||
VT_COL_LOG_TIME,
|
||||
VT_COL_IDLE_MSECS,
|
||||
VT_COL_LEVEL,
|
||||
VT_COL_MARK,
|
||||
VT_COL_MAX
|
||||
};
|
||||
|
||||
@ -113,6 +114,7 @@ public:
|
||||
virtual void get_foreign_keys(std::vector<std::string> &keys_inout)
|
||||
{
|
||||
keys_inout.push_back("log_line");
|
||||
keys_inout.push_back("log_mark");
|
||||
};
|
||||
|
||||
virtual void extract(logfile *lf,
|
||||
|
@ -206,7 +206,6 @@ void logfile::process_prefix(off_t offset, char *prefix, int len)
|
||||
* Assume this line is part of the previous one(s) and copy the
|
||||
* metadata over.
|
||||
*/
|
||||
ll.set_multiline();
|
||||
last_time = ll.get_time();
|
||||
last_millis = ll.get_millis();
|
||||
if (this->lf_format.get() != NULL) {
|
||||
|
@ -590,22 +590,28 @@ void logfile_sub_source::text_update_marks(vis_bookmarks &bm)
|
||||
content_line_t cl = this->lss_index[vl];
|
||||
logfile * lf;
|
||||
|
||||
lf = this->find(cl);
|
||||
|
||||
for (bookmarks<content_line_t>::type::iterator iter =
|
||||
this->lss_user_marks.begin();
|
||||
iter != this->lss_user_marks.end();
|
||||
++iter) {
|
||||
if (binary_search(iter->second.begin(), iter->second.end(), cl)) {
|
||||
bm[iter->first].insert_once(vl);
|
||||
|
||||
if (iter->first == &textview_curses::BM_USER) {
|
||||
logfile::iterator ll = lf->begin() + cl;
|
||||
|
||||
ll->set_mark(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lf = this->find(cl);
|
||||
|
||||
if (lf != last_file) {
|
||||
bm[&BM_FILES].insert_once(vl);
|
||||
}
|
||||
|
||||
switch ((*lf)[cl].get_level() & ~logline::LEVEL_MULTILINE) {
|
||||
switch ((*lf)[cl].get_level() & ~logline::LEVEL_MARK) {
|
||||
case logline::LEVEL_WARNING:
|
||||
bm[&BM_WARNINGS].insert_once(vl);
|
||||
break;
|
||||
|
@ -154,6 +154,11 @@ public:
|
||||
content_line_t cl = this->lss_index[line];
|
||||
std::vector<content_line_t>::iterator lb;
|
||||
|
||||
if (bm == &textview_curses::BM_USER) {
|
||||
logline *ll = this->find_line(cl);
|
||||
|
||||
ll->set_mark(added);
|
||||
}
|
||||
lb = std::lower_bound(this->lss_user_marks[bm].begin(),
|
||||
this->lss_user_marks[bm].end(),
|
||||
cl);
|
||||
@ -171,6 +176,15 @@ public:
|
||||
|
||||
void text_clear_marks(bookmark_type_t *bm)
|
||||
{
|
||||
std::vector<content_line_t>::iterator iter;
|
||||
|
||||
if (bm == &textview_curses::BM_USER) {
|
||||
for (iter = this->lss_user_marks[bm].begin();
|
||||
iter != this->lss_user_marks[bm].end();
|
||||
++iter) {
|
||||
this->find_line(*iter)->set_mark(false);
|
||||
}
|
||||
}
|
||||
this->lss_user_marks[bm].clear();
|
||||
};
|
||||
|
||||
@ -237,30 +251,6 @@ public:
|
||||
|
||||
void text_update_marks(vis_bookmarks &bm);
|
||||
|
||||
void toggle_user_mark(bookmark_type_t *bm,
|
||||
vis_line_t start_line,
|
||||
vis_line_t end_line = vis_line_t(-1))
|
||||
{
|
||||
if (end_line == -1) {
|
||||
end_line = start_line;
|
||||
}
|
||||
if (start_line > end_line) {
|
||||
std::swap(start_line, end_line);
|
||||
}
|
||||
for (vis_line_t curr_line = start_line; curr_line <= end_line;
|
||||
++curr_line) {
|
||||
bookmark_vector<content_line_t> &bv =
|
||||
this->lss_user_marks[bm];
|
||||
bookmark_vector<content_line_t>::iterator iter;
|
||||
|
||||
iter = bv.insert_once(this->at(curr_line));
|
||||
if (iter == bv.end()) {}
|
||||
else {
|
||||
bv.erase(iter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void set_user_mark(bookmark_type_t *bm, content_line_t cl)
|
||||
{
|
||||
this->lss_user_marks[bm].insert_once(cl);
|
||||
|
@ -248,6 +248,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked) {
|
||||
bookmark_vector<vis_line_t> &bv = this->tc_bookmarks[bm];
|
||||
bookmark_vector<vis_line_t>::iterator iter;
|
||||
|
||||
if (marked) {
|
||||
bv.insert_once(vl);
|
||||
}
|
||||
else {
|
||||
iter = std::lower_bound(bv.begin(), bv.end(), vl);
|
||||
if (iter != bv.end() && *iter == vl) {
|
||||
bv.erase(iter);
|
||||
}
|
||||
}
|
||||
if (this->tc_sub_source != NULL) {
|
||||
this->tc_sub_source->text_mark(bm, (int)vl, marked);
|
||||
}
|
||||
};
|
||||
|
||||
void set_sub_source(text_sub_source *src)
|
||||
{
|
||||
this->tc_sub_source = src;
|
||||
|
Loading…
Reference in New Issue
Block a user