/// <summary> /// Updates the line index centred around 'filepos'. /// If 'filepos' is within the current byte range of 'm_line_index' then an incremental search /// for lines is done in the direction needed to re-centre the line list around 'filepos'. /// If 'reload' is true a full rebuild of the cache is done</summary> public void Build(long filepos, bool reload, IList <IFilter> filters) { // Incremental updates cannot interrupt full reloads if (m_reload_in_progress && reload == false) { return; } m_reload_in_progress = reload; // Increment the build issue number to cancel any previous builds Interlocked.Increment(ref m_issue); var issue = m_issue; // Make a copy of the current state var state = m_state; // The index that 'filepos' would have in 'm_line_index'. // -1 if 'filepos' is before the current cached range, // or 'm_line_index.Count' if after state.m_index_centre = FindIndex(m_line_index, filepos); state.m_index_count = m_line_index.Count; // Make a copy of the filters state.m_filters = new List <IFilter>(filters); // Start a build in a worker thread ThreadPool.QueueUserWorkItem(BuildWorker); void BuildWorker(object _) { try { // Open a new stream to the log data using (var src = Src.OpenStream()) { // Determine new state properties of the file state.m_fileend = src.Length; state.m_filepos = Math_.Clamp(filepos, 0, state.m_fileend); // Do the update var lines = BuildAsync(ref state, src, reload, Progress); // Add the lines to the line index m_dispatcher.BeginInvoke(new Action(() => { MergeResults(state, lines, reload, Progress); })); } } catch (Exception ex) { m_dispatcher.BeginInvoke(new Action(() => { BuildError?.Invoke(this, new BuildErrorEventArgs(ex)); })); } finally { m_dispatcher.BeginInvoke(new Action(() => { if (!Progress(1, 1)) { return; } m_reload_in_progress = false; })); } } bool Progress(long scanned, long length) { m_dispatcher.BeginInvoke(new Action(() => { if (IsBuildCancelled(issue)) { return; } BuildProgress?.Invoke(this, new BuildProgressEventArgs(scanned, length)); })); return(!IsBuildCancelled(issue)); } }