/// <summary> /// Performs a low-level scan of the storage file to yield all Key/Value pairs it was able to read from the file. /// </summary> /// <param name="options"> The options normally used to create the <see cref="BPlusTree{TKey, TValue}"/> instance </param> /// <param name="sharing"> <see cref="FileShare"/> options used to open the file </param> /// <returns> Yields the Key/Value pairs found in the file </returns> public static IEnumerable <KeyValuePair <TKey, TValue> > RecoveryScan(Options options, FileShare sharing) { options = options.Clone(); options.CreateFile = CreatePolicy.Never; string filename = options.FileName; if (String.IsNullOrEmpty(filename)) { throw new InvalidConfigurationValueException("FileName", "The FileName property was not specified."); } if (!File.Exists(filename)) { throw new InvalidConfigurationValueException("FileName", "The FileName specified does not exist."); } if (options.StorageType != StorageType.Disk) { throw new InvalidConfigurationValueException("StorageType", "The storage type is not set to 'Disk'."); } using (FragmentedFile file = new FragmentedFile(filename, options.FileBlockSize, 1, 1, FileAccess.Read, sharing, FileOptions.None)) { NodeSerializer nodeReader = new NodeSerializer(options, new NodeHandleSerializer(new Storage.BTreeFileStore.HandleSerializer())); foreach (KeyValuePair <long, Stream> block in file.ForeachBlock(true, false, IngoreDataInvalid)) { List <KeyValuePair <TKey, TValue> > found = new List <KeyValuePair <TKey, TValue> >(); try { foreach (KeyValuePair <TKey, TValue> entry in nodeReader.RecoverLeaf(block.Value)) { found.Add(entry); } } catch { /* Serialization error: Ignore and continue */ } foreach (KeyValuePair <TKey, TValue> entry in found) { yield return(entry); } } } }