private line parse_line(sub_string l) { Debug.Assert(syntaxes_.Count > 0); foreach (var si in syntaxes_) { line result = null; if (si.relative_syntax_) { result = parse_relative_line(l, si); } else { result = parse_line_with_syntax(l, si); } if (result != null) { return(result); } } // in this case, we can't parse the line at all - use default return(new line(l, syntax_info.line_contains_msg_only_)); }
// returns null if it can't parse private line parse_line_with_syntax(sub_string l, syntax_info si) { if (si.relative_syntax_) { return(parse_relative_line(l, si)); } try { string sub = l.msg; bool normal_line = parse_time(sub, si.idx_in_line_[(int)info_type.time]) && parse_date(sub, si.idx_in_line_[(int)info_type.date]); if (si.idx_in_line_[(int)info_type.time].Item1 < 0 && si.idx_in_line_[(int)info_type.date].Item1 < 0) { // in this case, we don't have time & date - see that the level matches // note: we can't rely on level too much, since the user might have additional levels that our defaults - so we could get false negatives normal_line = parse_level(sub, si.idx_in_line_[(int)info_type.level]); } return(normal_line ? new line(l, si.idx_in_line_) : null); } catch (Exception e) { logger.Error("invalid line: " + l + " : " + e.Message); //return new line(pos_in_log, l, line_contains_msg_only_); return(null); } }
private line parse_relative_line(sub_string l, syntax_info si) { List <Tuple <int, int> > indexes = new List <Tuple <int, int> >(); for (int i = 0; i < (int)info_type.max; ++i) { indexes.Add(new Tuple <int, int>(-1, -1)); } string sub = l.msg; int cur_idx = 0; int correct_count = 0; foreach (var rel in si.relative_idx_in_line_) { if (cur_idx < 0) { break; } var index = parse_relative_part(sub, rel, ref cur_idx); if (index == null) { return(null); } if (index.Item1 >= 0) { indexes[(int)rel.type] = index; ++correct_count; } } // if we could parse time or date, we consider it an OK line bool normal_line = correct_count == si.relative_idx_in_line_.Count; return(normal_line ? new line(l, indexes.ToArray()) : null); }
private line parse_line(sub_string l) { Debug.Assert(syntaxes_.Count > 0); foreach (var si in syntaxes_) { line result = null; if (si.relative_syntax_) result = parse_relative_line(l, si); else result = parse_line_with_syntax(l, si); if (result != null) return result; } // in this case, we can't parse the line at all - use default return new line(l, syntax_info.line_contains_msg_only_); }
// returns null if it can't parse private line parse_line_with_syntax(sub_string l, syntax_info si) { if (si.relative_syntax_) return parse_relative_line(l, si); try { string sub = l.msg; bool normal_line = parse_time(sub, si.idx_in_line_[(int) info_type.time]) && parse_date(sub, si.idx_in_line_[(int) info_type.date]); if (si.idx_in_line_[(int) info_type.time].Item1 < 0 && si.idx_in_line_[(int) info_type.date].Item1 < 0) // in this case, we don't have time & date - see that the level matches // note: we can't rely on level too much, since the user might have additional levels that our defaults - so we could get false negatives normal_line = parse_level(sub, si.idx_in_line_[(int) info_type.level]); return normal_line ? new line(l, si.idx_in_line_) : null; } catch(Exception e) { logger.Error("invalid line: " + l + " : " + e.Message); //return new line(pos_in_log, l, line_contains_msg_only_); return null; } }
private line parse_relative_line(sub_string l, syntax_info si) { List< Tuple<int,int> > indexes = new List<Tuple<int, int>>(); for ( int i = 0; i < (int)info_type.max; ++i) indexes.Add(new Tuple<int,int>(-1,-1)); string sub = l.msg; int cur_idx = 0; int correct_count = 0; foreach (var rel in si.relative_idx_in_line_) { if (cur_idx < 0) break; var index = parse_relative_part(sub, rel, ref cur_idx); if (index == null) return null; if (index.Item1 >= 0 && index.Item2 >= 0) { indexes[(int) rel.type] = index; ++correct_count; } } // if we could parse time or date, we consider it an OK line bool normal_line = correct_count == si.relative_idx_in_line_.Count; return normal_line ? new line(l, indexes.ToArray()) : null ; }
public override void read_to_end() { ulong old_len = reader_.full_len; reader_.compute_full_length(); ulong new_len = reader_.full_len; // when reader's position is zero -> it's either the first time, or file was re-rewritten if (old_len > new_len || reader_.pos == 0) { // file got re-written force_reload(); } bool fully_read = old_len == new_len && reader_.is_up_to_date(); if (!reader_.has_more_cached_text()) { lock (this) { up_to_date_ = fully_read; if (up_to_date_) { // at this point, we're sure we read everything was_last_line_incomplete_ = DateTime.MinValue; } } return; } lock (this) up_to_date_ = false; string text = reader_.read_next_text(); int added_line_count = 0; bool was_last_line_incomplete = false, is_last_line_incomplete = false; int old_line_count = string_.line_count; string_.add_lines(text, ref added_line_count, ref was_last_line_incomplete, ref is_last_line_incomplete); if (added_line_count < 1) { return; } bool needs_reparse_last_line; lock (this) needs_reparse_last_line = lines_.Count > 0 && was_last_line_incomplete; int start_idx = old_line_count - (was_last_line_incomplete ? 1 : 0); int end_idx = string_.line_count; List <line> now = new List <line>(end_idx - start_idx); int merged_line_count = 0; for (int i = start_idx; i < end_idx; ++i) { var cur_line = new sub_string(string_, i - merged_line_count); bool is_from_prev_line = false; if (if_line_starts_with_tab_assume_from_prev_line) { if (cur_line.msg.StartsWith("\t")) { is_from_prev_line = true; } } if (i == 0) { is_from_prev_line = false; // there's no previous line } if (!is_from_prev_line) { now.Add(parse_line(cur_line)); } else { string_.merge_line_into_previous_line(i - merged_line_count); ++merged_line_count; } } lock (this) { if (needs_reparse_last_line) { // we re-parse the last line (which was previously incomplete) logger.Debug("[line] reparsed line " + (old_line_count - 1)); lines_.RemoveAt(lines_.Count - 1); } int old_count = lines_.Count; lines_.AddRange(now); // in order to adjust time, we have to have at least one syntax in which we find it bool can_find_time = syntaxes_.FirstOrDefault(x => x.can_find(info_type.time)) != null; if (can_find_time) { for (int idx = old_count; idx < lines_.Count; ++idx) { adjust_line_time(idx); } } was_last_line_incomplete_ = was_last_line_incomplete ? DateTime.Now : DateTime.MinValue; } //Debug.Assert( lines_.Count == string_.line_count); update_log_lines_capacity(); }
public override void read_to_end() { ulong old_len = reader_.full_len; reader_.compute_full_length(); ulong new_len = reader_.full_len; // when reader's position is zero -> it's either the first time, or file was re-rewritten if (old_len > new_len || reader_.pos == 0) // file got re-written force_reload(); bool fully_read = old_len == new_len && reader_.is_up_to_date(); if ( !reader_.has_more_cached_text()) { lock (this) { up_to_date_ = fully_read; if ( up_to_date_) // at this point, we're sure we read everything was_last_line_incomplete_ = DateTime.MinValue; } return; } lock (this) up_to_date_ = false; string text = reader_.read_next_text(); int added_line_count = 0; bool was_last_line_incomplete = false, is_last_line_incomplete = false; int old_line_count = string_.line_count; string_.add_lines(text, ref added_line_count, ref was_last_line_incomplete, ref is_last_line_incomplete); if (added_line_count < 1) return; bool needs_reparse_last_line; lock (this) needs_reparse_last_line = lines_.Count > 0 && was_last_line_incomplete ; int start_idx = old_line_count - (was_last_line_incomplete ? 1 : 0); int end_idx = string_.line_count; List<line> now = new List<line>(end_idx - start_idx); int merged_line_count = 0; for (int i = start_idx; i < end_idx; ++i) { var cur_line = new sub_string(string_, i - merged_line_count); bool is_from_prev_line = false; if ( if_line_starts_with_tab_assume_from_prev_line) if (cur_line.msg.StartsWith("\t")) is_from_prev_line = true; if (i == 0) is_from_prev_line = false; // there's no previous line if (!is_from_prev_line) now.Add(parse_line(cur_line)); else { string_.merge_line_into_previous_line(i - merged_line_count); ++merged_line_count; } } lock (this) { if (needs_reparse_last_line) { // we re-parse the last line (which was previously incomplete) logger.Debug("[line] reparsed line " + (old_line_count-1) ); lines_.RemoveAt( lines_.Count - 1); } int old_count = lines_.Count; lines_.AddRange(now); // in order to adjust time, we have to have at least one syntax in which we find it bool can_find_time = syntaxes_.FirstOrDefault(x => x.can_find(info_type.time)) != null; if ( can_find_time) for ( int idx = old_count; idx < lines_.Count; ++idx) adjust_line_time(idx); was_last_line_incomplete_ = was_last_line_incomplete ? DateTime.Now : DateTime.MinValue; } Debug.Assert( lines_.Count == string_.line_count); update_log_lines_capacity(); }