private void read_to_end() { ulong old_len = text_reader_.full_len; text_reader_.compute_full_length(); ulong new_len = text_reader_.full_len; if (old_len > new_len) { // file got re-written force_reload(); } bool fully_read = old_len == new_len && text_reader_.is_up_to_date(); ulong pos_in_log; lock (this) pos_in_log = last_pos_; text_reader_.pos = pos_in_log; int remaining = (int)(text_reader_.full_len - text_reader_.pos); if (remaining < 1) { lock (this) up_to_date_ = fully_read; return; } lock (this) up_to_date_ = false; string[] cur_lines = text_reader_.read_next_text(remaining).Split(new string[] { LINE_SEP }, StringSplitOptions.None); if (cur_lines.Length < 1) { return; } int start_idx = 0; var first_line = parse_line(cur_lines[0], pos_in_log); lock (this) if (lines_.Count > 0 && was_last_line_incomplete_) { // we re-parse the last line (which was previously incomplete) lines_[lines_.Count - 1] = first_line; pos_in_log += (ulong)cur_lines[0].Length + (ulong)LINE_SEP.Length; start_idx = 1; } int end_idx = cur_lines.Length; // find the first non-empty line for (; end_idx > 0 && cur_lines[end_idx - 1] == ""; --end_idx) { } List <line> now = new List <line>(); for (int i = start_idx; i < end_idx; ++i) { now.Add(parse_line(cur_lines[i], pos_in_log)); pos_in_log += (ulong)cur_lines[i].Length + (ulong)LINE_SEP.Length; } int old_count; lock (this) { old_count = lines_.Count; lines_.AddRange(now); for (int idx = old_count; idx < lines_.Count; ++idx) { adjust_line_time(idx); } was_last_line_incomplete_ = cur_lines[cur_lines.Length - 1] != ""; last_pos_ = pos_in_log; } }