/// <summary> /// Replay the entire log file to the provided dictionary interface /// </summary> public void ReplayLog(BPlusTree <TKey, TValue> target) { long position = 0L; ReplayLog(target, ref position); }
/// <summary> /// Recovers as much file content as possible into a newly created <see cref="BPlusTree{TKey, TValue}"/>, if the operation returns /// a non-zero result it was successful and the file has been replaced with a new database containing /// the recovered data. The original file remains in-tact but was renamed with a '.deleted' extension. /// </summary> /// <remarks> /// If an exception occurs during the parsing of the file and one or more records were recovered, they will /// be stored in a file by the same name with an added extension of '.recovered'. This recovered file can be /// opened as a normal <see cref="BPlusTree{TKey, TValue}"/> to view it's contents. During the restore it is possible that /// a single Key was found multiple times, in this case the first occurrence found will be used. /// </remarks> /// <param name="options"> The options normally used to create the <see cref="BPlusTree{TKey, TValue}"/> instance </param> /// <returns>Returns 0 on failure, or the number of records successfully retrieved from the original file </returns> public static int RecoverFile(Options options) { int recoveredCount = 0; 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'."); } int ix = 0; string tmpfilename = filename + ".recovered"; while (File.Exists(tmpfilename)) { tmpfilename = filename + ".recovered" + ix++; } try { BPlusTreeOptions <TKey, TValue> tmpoptions = options.Clone(); tmpoptions.CreateFile = CreatePolicy.Always; tmpoptions.FileName = tmpfilename; tmpoptions.LockingFactory = new LockFactory <IgnoreLocking>(); using (BPlusTree <TKey, TValue> tmpFile = new BPlusTree <TKey, TValue>(tmpoptions)) { BulkInsertOptions bulkOptions = new BulkInsertOptions(); bulkOptions.DuplicateHandling = DuplicateHandling.LastValueWins; recoveredCount = tmpFile.BulkInsert(RecoveryScan(options, FileShare.None), bulkOptions); } } finally { if (recoveredCount == 0 && File.Exists(tmpfilename)) { File.Delete(tmpfilename); } } if (recoveredCount > 0) { ix = 0; string backupName = filename + ".deleted"; while (File.Exists(backupName)) { backupName = filename + ".deleted" + ix++; } File.Move(filename, backupName); try { File.Move(tmpfilename, filename); } catch { File.Move(backupName, filename); throw; } } return(recoveredCount); }
public Enumerator(BPlusTree <TKey, TValue> tree, TKey startKey, Predicate <KeyValuePair <TKey, TValue> > fnContinue) : this(tree, startKey) { _fnContinue = fnContinue; }