상속: StreamDataAdapter
예제 #1
0
        IEnumerator<object> SearchInFiles(SearchQuery search, BlockingQueue<string> filenames, IFuture completionFuture)
        {
            var searchedFiles = new List<string>();
            var buffer = new List<SearchResult>();
            var sb = new StringBuilder();

            int numFiles = 0;

            using (Finally.Do(() => {
                SetSearchResults(buffer);
                lblStatus.Text = String.Format("{0} result(s) found.", buffer.Count);
                pbProgress.Style = ProgressBarStyle.Continuous;
                pbProgress.Value = 0;
            }))
            while (filenames.Count > 0 || !completionFuture.Completed) {
                var f = filenames.Dequeue();
                yield return f;

                var filename = f.Result as string;

                if (filename == null)
                    continue;
                if (searchedFiles.Contains(filename))
                    continue;

                if (PendingSearchQuery != null)
                    break;

                searchedFiles.Add(filename);

                int lineNumber = 0;
                var lineBuffer = new LineEntry[3];

                var insertResult = (Action)(() => {
                    var item = new SearchResult();
                    item.Filename = filename;
                    item.LineNumber = lineBuffer[1].LineNumber;

                    sb.Remove(0, sb.Length);
                    for (int i = 0; i < 3; i++) {
                        if (lineBuffer[i].Text != null) {
                            var line = lineBuffer[i].Text;
                            if (line.Length > 512)
                                line = line.Substring(0, 512);
                            sb.Append(line);
                        }

                        if (i < 2)
                            sb.Append("\r\n");
                    }
                    item.Context = sb.ToString();

                    buffer.Add(item);

                    if ((buffer.Count % 250 == 0) || ((buffer.Count < 50) && (buffer.Count % 5 == 1)))
                        SetSearchResults(buffer);
                });

                var stepSearch = (Action)(() => {
                    string currentLine = lineBuffer[1].Text;

                    if ((currentLine != null) && search.Regex.IsMatch(currentLine))
                        insertResult();
                });

                var insertLine = (Action<LineEntry>)((line) => {
                    lineBuffer[0] = lineBuffer[1];
                    lineBuffer[1] = lineBuffer[2];
                    lineBuffer[2] = line;

                    stepSearch();
                });

                numFiles += 1;
                if (numFiles % 50 == 0) {
                    lblStatus.Text = String.Format("Scanning '{0}'...", filename);
                    if (completionFuture.Completed) {
                        int totalNumFiles = numFiles + filenames.Count;
                        int progress = (numFiles * 1000 / totalNumFiles);

                        if (pbProgress.Value != progress)
                            pbProgress.Value = progress;
                        if (pbProgress.Style != ProgressBarStyle.Continuous)
                            pbProgress.Style = ProgressBarStyle.Continuous;
                    }
                }

                FileDataAdapter adapter = null;
                try {
                    adapter = new FileDataAdapter(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
                } catch {
                    if (adapter != null)
                        adapter.Dispose();
                    continue;
                }
                using (adapter) {
                    var fEncoding = Future.RunInThread(
                        () => DetectEncoding(adapter.BaseStream)
                    );
                    yield return fEncoding;

                    Future<string> thisLine = null, nextLine = null;

                    using (var reader = new AsyncTextReader(adapter, fEncoding.Result, SearchBufferSize))
                    while (true) {
                        thisLine = nextLine;

                        if (thisLine != null)
                            yield return thisLine;

                        nextLine = reader.ReadLine();

                        if (thisLine == null)
                            continue;

                        lineNumber += 1;
                        string line = thisLine.Result;
                        insertLine(new LineEntry { Text = line, LineNumber = lineNumber });

                        if (line == null)
                            break;
                        if (PendingSearchQuery != null)
                            break;

                        if (lineNumber % 10000 == 5000) {
                            var newStatus = String.Format("Scanning '{0}'... (line {1})", filename, lineNumber);
                            if (lblStatus.Text != newStatus)
                                lblStatus.Text = newStatus;
                        }
                    }
                }
            }
        }
예제 #2
0
        protected IEnumerator<object> SnapshotIOTask()
        {
            ActivityIndicator.Item progress = null;
            IFuture previousSnapshot = null;

            while (true) {
                if ((SnapshotLoadQueue.Count <= 0) && (previousSnapshot != null))
                    yield return previousSnapshot;

                if (SnapshotLoadQueue.Count <= 0) {
                    SnapshotLoadState.Count = 0;
                    if (progress != null) {
                        progress.Dispose();
                        progress = null;
                    }
                }

                var f = SnapshotLoadQueue.Dequeue();
                using (f)
                    yield return f;

                var filename = f.Result;

                if (progress == null)
                    progress = Activities.AddItem("Loading snapshots");

                using (var fda = new FileDataAdapter(
                    filename, FileMode.Open,
                    FileAccess.Read, FileShare.Read, 1024 * 128
                )) {
                    var maximum = SnapshotLoadState.Count + Math.Max(0, SnapshotLoadQueue.Count) + 1;
                    progress.Maximum = maximum;
                    progress.Progress = Math.Min(maximum, SnapshotLoadState.Count);

                    var fBytes = fda.ReadToEnd();
                    yield return fBytes;

                    var fText = Future.RunInThread(
                        () => Encoding.ASCII.GetString(fBytes.Result)
                    );
                    yield return fText;

                    var text = fText.Result;
                    fBytes = null;
                    fText = null;

                    // Wait for the last snapshot load we triggered to finish
                    if (previousSnapshot != null)
                        yield return previousSnapshot;

                    previousSnapshot = Scheduler.Start(
                        FinishLoadingSnapshot(filename, text), TaskExecutionPolicy.RunAsBackgroundTask
                    );

                    text = null;
                }
            }
        }
예제 #3
0
        public static IEnumerator<object> FromFile(string filename, IProgressListener progress)
        {
            progress.Status = "Loading diff...";

            Future<string> fText;

            // We could stream the lines in from the IO thread while we parse them, but this
            //  part of the load is usually pretty quick even on a regular hard disk, and
            //  loading the whole diff at once eliminates some context switches
            using (var fda = new FileDataAdapter(
                filename, FileMode.Open,
                FileAccess.Read, FileShare.Read, 1024 * 128
            )) {
                var fBytes = fda.ReadToEnd();
                yield return fBytes;

                fText = Future.RunInThread(
                    () => Encoding.ASCII.GetString(fBytes.Result)
                );
                yield return fText;
            }

            yield return fText;
            var lr = new LineReader(fText.Result);
            LineReader.Line line;

            progress.Status = "Parsing diff...";

            var frames = new List<TracebackFrame>();
            var moduleNames = new NameTable(StringComparer.Ordinal);
            var symbolTypes = new NameTable(StringComparer.Ordinal);
            var functionNames = new NameTable(StringComparer.Ordinal);
            var deltas = new List<DeltaInfo>();
            var tracebacks = new Dictionary<UInt32, TracebackInfo>();

            var regexes = new Regexes();

            // Regex.Groups[string] does an inefficient lookup, so we do that lookup once here
            int groupModule = regexes.DiffModule.GroupNumberFromName("module");
            int groupSymbolType = regexes.DiffModule.GroupNumberFromName("symbol_type");
            int groupTraceId = regexes.BytesDelta.GroupNumberFromName("trace_id");
            int groupType = regexes.BytesDelta.GroupNumberFromName("type");
            int groupDeltaBytes = regexes.BytesDelta.GroupNumberFromName("delta_bytes");
            int groupNewBytes = regexes.BytesDelta.GroupNumberFromName("new_bytes");
            int groupOldBytes = regexes.BytesDelta.GroupNumberFromName("old_bytes");
            int groupNewCount = regexes.BytesDelta.GroupNumberFromName("new_count");
            int groupOldCount = regexes.CountDelta.GroupNumberFromName("old_count");
            int groupCountDelta = regexes.CountDelta.GroupNumberFromName("delta_count");
            int groupTracebackModule = regexes.TracebackFrame.GroupNumberFromName("module");
            int groupTracebackFunction = regexes.TracebackFrame.GroupNumberFromName("function");
            int groupTracebackOffset = regexes.TracebackFrame.GroupNumberFromName("offset");
            int groupTracebackOffset2 = regexes.TracebackFrame.GroupNumberFromName("offset2");
            int groupTracebackPath = regexes.TracebackFrame.GroupNumberFromName("path");
            int groupTracebackLine = regexes.TracebackFrame.GroupNumberFromName("line");

            int i = 0;
            while (lr.ReadLine(out line)) {
                if (i % ProgressInterval == 0) {
                    progress.Maximum = lr.Length;
                    progress.Progress = lr.Position;

                    // Suspend processing until any messages in the windows message queue have been processed
                    yield return new Yield();
                }

            retryFromHere:

                Match m;
                if (regexes.DiffModule.TryMatch(ref line, out m)) {
                    moduleNames.Add(m.Groups[groupModule].Value);
                } else if (regexes.BytesDelta.TryMatch(ref line, out m)) {
                    var traceId = UInt32.Parse(m.Groups[groupTraceId].Value, NumberStyles.HexNumber);
                    var info = new DeltaInfo {
                        Added = (m.Groups[groupType].Value == "+"),
                        BytesDelta = int.Parse(m.Groups[groupDeltaBytes].Value, NumberStyles.HexNumber),
                        NewBytes = int.Parse(m.Groups[groupNewBytes].Value, NumberStyles.HexNumber),
                        OldBytes = int.Parse(m.Groups[groupOldBytes].Value, NumberStyles.HexNumber),
                        NewCount = int.Parse(m.Groups[groupNewCount].Value, NumberStyles.HexNumber),
                    };

                    if (lr.ReadLine(out line)) {
                        if (regexes.CountDelta.TryMatch(ref line, out m)) {
                            info.OldCount = int.Parse(m.Groups[groupOldCount].Value, NumberStyles.HexNumber);
                            info.CountDelta = int.Parse(m.Groups[groupCountDelta].Value, NumberStyles.HexNumber);
                        }
                    }

                    bool readingLeadingWhitespace = true, doRetry = false;

                    frames.Clear();
                    var itemModules = new NameTable(StringComparer.Ordinal);
                    var itemFunctions = new NameTable(StringComparer.Ordinal);

                    while (lr.ReadLine(out line)) {
                        if (line.ToString().Trim().Length == 0) {
                            if (readingLeadingWhitespace)
                                continue;
                            else
                                break;
                        } else if (regexes.TracebackFrame.TryMatch(ref line, out m)) {
                            readingLeadingWhitespace = false;

                            var moduleName = moduleNames[m.Groups[groupTracebackModule].Value];
                            itemModules.Add(moduleName);

                            var functionName = functionNames[m.Groups[groupTracebackFunction].Value];
                            itemFunctions.Add(functionName);

                            var frame = new TracebackFrame {
                                Module = moduleName,
                                Function = functionName,
                                Offset = UInt32.Parse(m.Groups[groupTracebackOffset].Value, NumberStyles.HexNumber)
                            };
                            if (m.Groups[groupTracebackOffset2].Success)
                                frame.Offset2 = UInt32.Parse(m.Groups[groupTracebackOffset2].Value, NumberStyles.HexNumber);

                            if (m.Groups[groupTracebackPath].Success)
                                frame.SourceFile = m.Groups[groupTracebackPath].Value;

                            if (m.Groups[groupTracebackLine].Success)
                                frame.SourceLine = int.Parse(m.Groups[groupTracebackLine].Value);

                            frames.Add(frame);
                        } else {
                            // We hit the beginning of a new allocation, so make sure it gets parsed
                            doRetry = true;
                            break;
                        }
                    }

                    if (tracebacks.ContainsKey(traceId)) {
                        info.Traceback = tracebacks[traceId];
                        Console.WriteLine("Duplicate traceback for id {0}!", traceId);
                    } else {
                        var frameArray = ImmutableArrayPool<TracebackFrame>.Allocate(frames.Count);
                        frames.CopyTo(frameArray.Array, frameArray.Offset);

                        info.Traceback = tracebacks[traceId] = new TracebackInfo {
                            TraceId = traceId,
                            Frames = frameArray,
                            Modules = itemModules,
                            Functions = itemFunctions
                        };
                    }

                    deltas.Add(info);

                    if (doRetry)
                        goto retryFromHere;
                } else if (line.StartsWith("//")) {
                    // Comment, ignore it
                } else if (line.StartsWith("Total increase") || line.StartsWith("Total decrease")) {
                    // Ignore this too
                } else if (line.StartsWith("         ") && (line.EndsWith(".pdb"))) {
                    // Symbol path for a module, ignore it
                } else {
                    Console.WriteLine("Unrecognized diff content: {0}", line.ToString());
                }
            }

            var result = new HeapDiff(
                filename, moduleNames, functionNames, deltas, tracebacks
            );
            yield return new Result(result);
        }