Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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;
 }