コード例 #1
0
ファイル: IncrementalBackup.cs プロジェクト: yitaom2/ravendb
        private static void Restore(StorageEnvironment env, IEnumerable <ZipArchiveEntry> entries, VoronPathSetting tempDir, List <IDisposable> toDispose,
                                    LowLevelTransaction txw)
        {
            try
            {
                TransactionHeader *lastTxHeader = null;
                var  lastTxHeaderStackLocation  = stackalloc TransactionHeader[1];
                long lastTxId = env.HeaderAccessor.Get(x => x->TransactionId);

                long journalNumber = -1;
                foreach (var entry in entries)
                {
                    switch (Path.GetExtension(entry.Name))
                    {
                    case ".merged-journal":
                    case ".journal":

                        var jounalFileName = tempDir.Combine(entry.Name);
                        using (var output = SafeFileStream.Create(jounalFileName.FullPath, FileMode.Create))
                            using (var input = entry.Open())
                            {
                                output.Position = output.Length;
                                input.CopyTo(output);
                            }

                        var pager = env.Options.OpenPager(jounalFileName);
                        toDispose.Add(pager);

                        if (long.TryParse(Path.GetFileNameWithoutExtension(entry.Name), out journalNumber) == false)
                        {
                            throw new InvalidOperationException("Cannot parse journal file number");
                        }

                        var recoveryPager =
                            env.Options.CreateTemporaryBufferPager(Path.Combine(tempDir.Combine(StorageEnvironmentOptions.JournalRecoveryName(journalNumber)).FullPath),
                                                                   env.Options.InitialFileSize ?? env.Options.InitialLogFileSize);
                        toDispose.Add(recoveryPager);

                        using (var reader = new JournalReader(pager, env.Options.DataPager, recoveryPager, new HashSet <long>(), new JournalInfo
                        {
                            LastSyncedTransactionId = lastTxId
                        }, lastTxHeader))
                        {
                            while (reader.ReadOneTransactionToDataFile(env.Options))
                            {
                                lastTxHeader = reader.LastTransactionHeader;
                            }

                            reader.ZeroRecoveryBufferIfNeeded(reader, env.Options);
                            if (lastTxHeader != null)
                            {
                                *lastTxHeaderStackLocation = *lastTxHeader;
                                lastTxHeader = lastTxHeaderStackLocation;
                                lastTxId     = lastTxHeader->TransactionId;
                            }
                        }

                        break;

                    default:
                        throw new InvalidOperationException("Unknown file, cannot restore: " + entry);
                    }
                }

                if (lastTxHeader == null)
                {
                    return; // there was no valid transactions, nothing to do
                }
                env.Options.DataPager.Sync(0);


                var root = Tree.Open(txw, null, Constants.RootTreeNameSlice, &lastTxHeader->Root);

                txw.UpdateRootsIfNeeded(root);

                txw.State.NextPageNumber = lastTxHeader->LastPageNumber + 1;

                txw.Commit();

                env.HeaderAccessor.Modify(header =>
                {
                    header->TransactionId  = lastTxHeader->TransactionId;
                    header->LastPageNumber = lastTxHeader->LastPageNumber;

                    header->Journal.LastSyncedTransactionId = lastTxHeader->TransactionId;

                    header->Root = lastTxHeader->Root;

                    Sparrow.Memory.Set(header->Journal.Reserved, 0, JournalInfo.NumberOfReservedBytes);
                    header->Journal.Flags = JournalInfoFlags.None;
                });
            }
            finally
            {
                toDispose.ForEach(x => x.Dispose());

                try
                {
                    Directory.Delete(tempDir.FullPath, true);
                }
                catch
                {
                    // this is just a temporary directory, the worst case scenario is that we dont reclaim the space from the OS temp directory
                    // if for some reason we cannot delete it we are safe to ignore it.
                }
            }
        }
コード例 #2
0
        private static void Restore(StorageEnvironment env, IEnumerable <ZipArchiveEntry> entries, string tempDir, List <IDisposable> toDispose,
                                    LowLevelTransaction txw)
        {
            try
            {
                TransactionHeader *lastTxHeader = null;

                long journalNumber = -1;
                foreach (var entry in entries)
                {
                    switch (Path.GetExtension(entry.Name))
                    {
                    case ".merged-journal":
                    case ".journal":

                        var jounalFileName = Path.Combine(tempDir, entry.Name);
                        using (var output = new FileStream(jounalFileName, FileMode.Create))
                            using (var input = entry.Open())
                            {
                                output.Position = output.Length;
                                input.CopyTo(output);
                            }

                        var pager = env.Options.OpenPager(jounalFileName);
                        toDispose.Add(pager);

                        if (long.TryParse(Path.GetFileNameWithoutExtension(entry.Name), out journalNumber) == false)
                        {
                            throw new InvalidOperationException("Cannot parse journal file number");
                        }

                        var recoveryPager =
                            env.Options.CreateScratchPager(Path.Combine(tempDir,
                                                                        StorageEnvironmentOptions.JournalRecoveryName(journalNumber)),
                                                           env.Options.InitialFileSize ?? env.Options.InitialLogFileSize);
                        toDispose.Add(recoveryPager);

                        using (
                            var reader = new JournalReader(pager, env.Options.DataPager, recoveryPager, 0,
                                                           lastTxHeader))
                        {
                            while (reader.ReadOneTransactionToDataFile(env.Options))
                            {
                                lastTxHeader = reader.LastTransactionHeader;
                            }
                        }
                        break;

                    default:
                        throw new InvalidOperationException("Unknown file, cannot restore: " + entry);
                    }
                }

                if (lastTxHeader == null)
                {
                    return; // there was no valid transactions, nothing to do
                }
                env.Options.DataPager.Sync();


                var root = Tree.Open(txw, null, &lastTxHeader->Root);
                root.Name = Constants.RootTreeNameSlice;

                txw.UpdateRootsIfNeeded(root);

                txw.State.NextPageNumber = lastTxHeader->LastPageNumber + 1;

                env.Journal.Clear(txw);

                txw.Commit();

                env.HeaderAccessor.Modify(header =>
                {
                    header->TransactionId  = lastTxHeader->TransactionId;
                    header->LastPageNumber = lastTxHeader->LastPageNumber;

                    header->Journal.LastSyncedJournal       = journalNumber;
                    header->Journal.LastSyncedTransactionId = lastTxHeader->TransactionId;

                    header->Root = lastTxHeader->Root;

                    header->Journal.CurrentJournal    = journalNumber + 1;
                    header->Journal.JournalFilesCount = 0;
                });
            }
            finally
            {
                toDispose.ForEach(x => x.Dispose());

                try
                {
                    Directory.Delete(tempDir, true);
                }
                catch
                {
                    // this is just a temporary directory, the worst case scenario is that we dont reclaim the space from the OS temp directory
                    // if for some reason we cannot delete it we are safe to ignore it.
                }
            }
        }