diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ac221b58..6e8d1aaf 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -57,7 +57,7 @@ log format has matched yet, each line will be passed through the log format regular expressions to try and find a match. Each line that is read is added to an index -### Why is `mmap()` not used? +#### Why is `mmap()` not used? Note that file contents are consumed using `pread(2)`/`read(2)` and not `mmap(2)` since `mmap(2)` does not react well to files changing out from @@ -71,10 +71,21 @@ As files are being indexed, if a matching format is found, the file is it is added to the [logfile_sub_source](src/logfile_sub_source.hh), which collates all log messages together into a single index. +## Log Formats + +[log_format](src/log_format.hh) instances are used to parse lines from files +into `logline` objects. The majority of log formats are +[external_log_format](src/log_format_ext.hh) objects that are create from +[JSON format definitions](https://lnav.readthedocs.io/en/latest/formats.html). +The built-in definitions are located in the [formats](src/formats) directory. +Log formats that cannot be handled through a simple regular expression are +implemented in the [log_format_impls.cc](src/log_format_impls.cc) file. + ## User Interface [![lnav TUI](docs/lnav-tui.png)](https://whimsical.com/lnav-tui-MQjXc7Vx23BxQTHrnuNp5F) The lnav text-user-interface is built on top of the basic drawing functionality -of [ncurses](https://invisible-island.net/ncurses/announce.html). However, - +provided by [ncurses](https://invisible-island.net/ncurses/announce.html). +However, the higher-level functionality of panels, widgets, and such is not +used. diff --git a/docs/lnav-architecture.png b/docs/lnav-architecture.png index 75414508..dc9fae9f 100644 Binary files a/docs/lnav-architecture.png and b/docs/lnav-architecture.png differ diff --git a/src/base/date_time_scanner.cc b/src/base/date_time_scanner.cc index 5089be3d..6e3aab8d 100644 --- a/src/base/date_time_scanner.cc +++ b/src/base/date_time_scanner.cc @@ -208,3 +208,33 @@ const char *date_time_scanner::scan(const char *time_dest, return retval; } + +void date_time_scanner::to_localtime(time_t t, exttm &tm_out) +{ + if (t < (24 * 60 * 60)) { + // Don't convert and risk going past the epoch. + return; + } + + if (t < this->dts_local_offset_valid || + t >= this->dts_local_offset_expiry) { + time_t new_gmt; + + localtime_r(&t, &tm_out.et_tm); +#ifdef HAVE_STRUCT_TM_TM_ZONE + tm_out.et_tm.tm_zone = nullptr; +#endif + tm_out.et_tm.tm_isdst = 0; + + new_gmt = tm2sec(&tm_out.et_tm); + this->dts_local_offset_cache = t - new_gmt; + this->dts_local_offset_valid = t; + this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1); + this->dts_local_offset_expiry -= + this->dts_local_offset_expiry % EXPIRE_TIME; + } + else { + time_t adjust_gmt = t - this->dts_local_offset_cache; + gmtime_r(&adjust_gmt, &tm_out.et_tm); + } +} diff --git a/src/base/date_time_scanner.hh b/src/base/date_time_scanner.hh index f95f525a..a85fd50c 100644 --- a/src/base/date_time_scanner.hh +++ b/src/base/date_time_scanner.hh @@ -39,12 +39,15 @@ #include "time_util.hh" +/** + * Scans a timestamp string to discover the date-time format using the custom + * ptimec parser. Once a format is found, it is locked in so that the next + * time a timestamp needs to be scanned, the format does not have to be + * rediscovered. The discovered date-time format can also be used to convert + * an exttm struct to a string using the ftime() method. + */ struct date_time_scanner { - date_time_scanner() : dts_keep_base_tz(false), - dts_local_time(false), - dts_local_offset_cache(0), - dts_local_offset_valid(0), - dts_local_offset_expiry(0) { + date_time_scanner() { this->clear(); }; @@ -55,6 +58,9 @@ struct date_time_scanner { this->dts_fmt_len = -1; }; + /** + * Unlock this scanner so that the format is rediscovered. + */ void unlock() { this->dts_fmt_lock = -1; this->dts_fmt_len = -1; @@ -72,44 +78,17 @@ struct date_time_scanner { * every call, so we cache the result and only call it again if the * requested time falls outside of a fifteen minute range. */ - void to_localtime(time_t t, struct exttm &tm_out) { - if (t < (24 * 60 * 60)) { - // Don't convert and risk going past the epoch. - return; - } + void to_localtime(time_t t, struct exttm &tm_out); - if (t < this->dts_local_offset_valid || - t >= this->dts_local_offset_expiry) { - time_t new_gmt; - - localtime_r(&t, &tm_out.et_tm); -#ifdef HAVE_STRUCT_TM_TM_ZONE - tm_out.et_tm.tm_zone = nullptr; -#endif - tm_out.et_tm.tm_isdst = 0; - - new_gmt = tm2sec(&tm_out.et_tm); - this->dts_local_offset_cache = t - new_gmt; - this->dts_local_offset_valid = t; - this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1); - this->dts_local_offset_expiry -= - this->dts_local_offset_expiry % EXPIRE_TIME; - } - else { - time_t adjust_gmt = t - this->dts_local_offset_cache; - gmtime_r(&adjust_gmt, &tm_out.et_tm); - } - }; - - bool dts_keep_base_tz; - bool dts_local_time; - time_t dts_base_time; + bool dts_keep_base_tz{false}; + bool dts_local_time{false}; + time_t dts_base_time{0}; struct exttm dts_base_tm; - int dts_fmt_lock; - int dts_fmt_len; - time_t dts_local_offset_cache; - time_t dts_local_offset_valid; - time_t dts_local_offset_expiry; + int dts_fmt_lock{-1}; + int dts_fmt_len{-1}; + time_t dts_local_offset_cache{0}; + time_t dts_local_offset_valid{0}; + time_t dts_local_offset_expiry{0}; static const int EXPIRE_TIME = 15 * 60; diff --git a/src/base/humanize.hh b/src/base/humanize.hh index fcbf2666..fc8dbffe 100644 --- a/src/base/humanize.hh +++ b/src/base/humanize.hh @@ -36,6 +36,12 @@ namespace humanize { +/** + * Format the given size as a human-friendly string. + * + * @param value The value to format. + * @return The formatted string. + */ std::string file_size(ssize_t value); } diff --git a/src/data_scanner_re.cc b/src/data_scanner_re.cc index e9302aa1..9154d30b 100644 --- a/src/data_scanner_re.cc +++ b/src/data_scanner_re.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 2.0.3 on Wed Jan 27 16:33:33 2021 */ +/* Generated by re2c 2.0.3 on Sat Feb 13 21:35:28 2021 */ #line 1 "../../lnav/src/data_scanner_re.re" /** * Copyright (c) 2015, Timothy Stack @@ -53,7 +53,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out) static const unsigned char *EMPTY = (const unsigned char *) ""; pcre_input &pi = this->ds_pcre_input; struct _YYCURSOR { - const YYCTYPE operator*() const { + YYCTYPE operator*() const { if (this->val < this->lim) { return *val; } diff --git a/src/data_scanner_re.re b/src/data_scanner_re.re index ce07c3d5..3b3e5e51 100644 --- a/src/data_scanner_re.re +++ b/src/data_scanner_re.re @@ -51,7 +51,7 @@ bool data_scanner::tokenize2(pcre_context &pc, data_token_t &token_out) static const unsigned char *EMPTY = (const unsigned char *) ""; pcre_input &pi = this->ds_pcre_input; struct _YYCURSOR { - const YYCTYPE operator*() const { + YYCTYPE operator*() const { if (this->val < this->lim) { return *val; } diff --git a/src/files_sub_source.cc b/src/files_sub_source.cc index d3c2bdbe..94ffe43c 100644 --- a/src/files_sub_source.cc +++ b/src/files_sub_source.cc @@ -62,9 +62,9 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch) auto& lss = lnav_data.ld_log_source; auto &lf = fc.fc_files[sel]; - lss.find_data(lf) | [&lss](auto ld) { + lss.find_data(lf) | [](auto ld) { ld->set_visibility(true); - lss.text_filters_changed(); + lnav_data.ld_log_source.text_filters_changed(); }; if (lf->get_format() != nullptr) { diff --git a/src/log_format_loader.cc b/src/log_format_loader.cc index afa7846a..3f9dd78d 100644 --- a/src/log_format_loader.cc +++ b/src/log_format_loader.cc @@ -792,7 +792,7 @@ static void write_sample_file() extract_metadata(sf.data(), sf.length(), meta); snprintf(path, sizeof(path), "formats/default/%s.lnav", meta.sm_name.c_str()); auto script_path = dotlnav_path() / path; - if (statp(script_path, &st) == 0 && (size_t) st.st_size == sf.length()) { + if (statp(script_path, &st) == 0 && st.st_size == sf.length()) { // Assume it's the right contents and move on... continue; } diff --git a/src/pcrepp/pcrepp.cc b/src/pcrepp/pcrepp.cc index 9f427276..551ac209 100644 --- a/src/pcrepp/pcrepp.cc +++ b/src/pcrepp/pcrepp.cc @@ -165,7 +165,7 @@ void pcrepp::find_captures(const char *pattern) } } - ensure(this->p_capture_count == this->p_captures.size()); + ensure((size_t) this->p_capture_count == this->p_captures.size()); } bool pcrepp::match(pcre_context &pc, pcre_input &pi, int options) const diff --git a/src/ptimec.c b/src/ptimec.c index a23e7084..2bd304a3 100644 --- a/src/ptimec.c +++ b/src/ptimec.c @@ -129,7 +129,7 @@ int main(int argc, char *argv[]) printf(" { \"%s\", ptime_f%d, ftime_f%d },\n", argv[lpc], lpc, lpc); } printf("\n"); - printf(" { NULL, NULL }\n"); + printf(" { nullptr, nullptr, nullptr }\n"); printf("};\n"); printf("const char *PTIMEC_FORMAT_STR[] = {\n"); @@ -137,7 +137,7 @@ int main(int argc, char *argv[]) printf(" \"%s\",\n", argv[lpc]); } printf("\n"); - printf(" NULL\n"); + printf(" nullptr\n"); printf("};\n"); return retval; diff --git a/src/ptimec.hh b/src/ptimec.hh index 025d4796..3c517e91 100644 --- a/src/ptimec.hh +++ b/src/ptimec.hh @@ -47,13 +47,13 @@ #include "base/time_util.hh" #define PTIME_CONSUME(amount, block) \ - if ((off_inout + amount) > len) { \ + if ((off_inout + (amount)) > len) { \ return false; \ } \ \ block \ \ - off_inout += amount; + off_inout += (amount); #define PTIME_APPEND(ch) \ if ((off_inout + 2) >= len) { \ diff --git a/src/views_vtab.cc b/src/views_vtab.cc index 7b6f726a..026f66ea 100644 --- a/src/views_vtab.cc +++ b/src/views_vtab.cc @@ -514,13 +514,13 @@ CREATE TABLE lnav_view_filters ( text_filter::type_t type, pair> pattern) { auto view_index = lnav_view_t(rowid >> 32); - int filter_index = rowid & 0xffffffffLL; + auto filter_index = rowid & 0xffffffffLL; textview_curses &tc = lnav_data.ld_views[view_index]; text_sub_source *tss = tc.get_sub_source(); filter_stack &fs = tss->get_filters(); auto iter = fs.begin(); for (; iter != fs.end(); ++iter) { - if ((*iter)->get_index() == filter_index) { + if ((*iter)->get_index() == (size_t) filter_index) { break; } }