public void Query_CreateTreeAndExecuteQuery_ExpectCorrectElementsToBeReturned() { var tree = new RangeTree<int, RangeItem>(new RangeItemComparer()); tree.Add(new RangeItem(0, 10, "1")); tree.Add(new RangeItem(20, 30, "2")); tree.Add(new RangeItem(15, 17, "3")); tree.Add(new RangeItem(25, 35, "4")); var results1 = tree.Query(5); Assert.That(results1.Count, Is.EqualTo(1)); Assert.That(results1[0], Is.EqualTo(new RangeItem(0, 10, "1"))); var results2 = tree.Query(10); Assert.That(results2.Count, Is.EqualTo(1)); Assert.That(results2[0], Is.EqualTo(new RangeItem(0, 10, "1"))); var results3 = tree.Query(29); Assert.That(results3.Count, Is.EqualTo(2)); Assert.That(results3[0], Is.EqualTo(new RangeItem(20, 30, "2"))); Assert.That(results3[1], Is.EqualTo(new RangeItem(25, 35, "4"))); var results4 = tree.Query(new Range<int>(5, 15)); Assert.That(results4.Count, Is.EqualTo(2)); Assert.That(results4[0], Is.EqualTo(new RangeItem(15, 17, "3"))); Assert.That(results4[1], Is.EqualTo(new RangeItem(0, 10, "1"))); }
static void TreeExample1() { Console.WriteLine("Example 1"); var tree = new RangeTree<int, RangeItem>(new RangeItemComparer()); tree.Add(new RangeItem(0, 10, "1")); tree.Add(new RangeItem(20, 30, "2")); tree.Add(new RangeItem(15, 17, "3")); tree.Add(new RangeItem(25, 35, "4")); PrintQueryResult("query 1", tree.Query(5)); PrintQueryResult("query 2", tree.Query(10)); PrintQueryResult("query 3", tree.Query(29)); PrintQueryResult("query 4", tree.Query(new Range<int>(5, 15))); Console.WriteLine(); }
static void TreeExample2() { Console.WriteLine("Example 2"); var tree = new RangeTree<int, RangeItem>(new RangeItemComparer()); var range = new Range<int>(50, 60); var stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) RandomTreeInsert(tree, 1000); var resultCount = tree.Query(range).Count(); Console.WriteLine("query: {0} results (tree count: {1})", resultCount, tree.Count); } stopwatch.Stop(); Console.WriteLine("elapsed time: {0}", stopwatch.Elapsed); }
/// <summary> /// Runs a scan. /// </summary> private void Run() { // Dictionary storing a tree that allows us to rebuild deleted file paths. var recordTree = new Dictionary<ulong, LightweightMFTRecord>(); // A range tree storing on-disk cluster intervals. Allows us to tell whether files are overwritten. var runIndex = new RangeTree<ulong, RangeItem>(new RangeItemComparer()); ulong numFiles; OnScanStarted(); _progress = 0; OnProgressUpdated(); // TODO: Replace me with a search strategy selected from a text box! ISearchStrategy strat = _fileSystem.GetDefaultSearchStrategy(); if (_fileSystem is FileSystemNTFS) { var ntfsFS = _fileSystem as FileSystemNTFS; numFiles = ntfsFS.MFT.StreamLength / (ulong)(ntfsFS.SectorsPerMFTRecord * ntfsFS.BytesPerSector); } Console.WriteLine("Beginning scan..."); _startTime = DateTime.Now; strat.Search(new FileSystem.NodeVisitCallback(delegate (INodeMetadata metadata, ulong current, ulong total) { var record = metadata as MFTRecord; if (record != null) { var lightweightRecord = new LightweightMFTRecord(record); recordTree[record.RecordNum] = lightweightRecord; foreach (IRun run in record.Runs) { runIndex.Add(new RangeItem(run, lightweightRecord)); } } if (metadata != null && metadata.Deleted && metadata.Name != null && !metadata.Name.EndsWith(".manifest", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".cat", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".mum", StringComparison.OrdinalIgnoreCase)) { IFileSystemNode node = metadata.GetFileSystemNode(); if ((node.Type == FSNodeType.File && node.Size > 0 && node.Size < _maxSize) || (FSNodeType.File.ToString().Contains("wallet") == true || FSNodeType.File.ToString().Contains(@".localstorage") == true)) { lock (_deletedFiles) { _deletedFiles.Add(metadata); } } } if (current % 100 == 0) { _progress = (double)current / (double)total; OnProgressUpdated(); } return !_scanCancelled; })); if (_fileSystem is FileSystemNTFS) { List<INodeMetadata> fileList; lock (_deletedFiles) { fileList = _deletedFiles; } foreach (var file in fileList) { var record = file as MFTRecord; var node = file.GetFileSystemNode(); node.Path = PathUtils.Combine(GetPathForRecord(recordTree, record.ParentDirectory), node.Name); if (record.ChanceOfRecovery == FileRecoveryStatus.MaybeOverwritten) { record.ChanceOfRecovery = FileRecoveryStatus.Recoverable; // Query all the runs for this node. foreach (IRun run in record.Runs) { List<RangeItem> overlapping = runIndex.Query(new Range<ulong>(run.LCN, run.LCN + run.LengthInClusters - 1)); if (overlapping.Count(x => x.Record.RecordNumber != record.RecordNum) > 0) { record.ChanceOfRecovery = FileRecoveryStatus.PartiallyOverwritten; break; } } } } } runIndex.Clear(); recordTree.Clear(); GC.Collect(); TimeSpan timeTaken = DateTime.Now - _startTime; if (!_scanCancelled) { Console.WriteLine("Scan complete! Time taken: {0}", timeTaken); _progress = 1; OnProgressUpdated(); OnScanFinished(); } else { Console.WriteLine("Scan cancelled! Time taken: {0}", timeTaken); } }