[sql] add a bookmark column to the log tables

This commit is contained in:
Timothy Stack 2014-03-01 23:40:12 -08:00
parent 7bcbd000ad
commit 10eb9617b1
11 changed files with 91 additions and 41 deletions

3
NEWS
View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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]);
}

View File

@ -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; };

View File

@ -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 */

View File

@ -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,

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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;