示例#1
0
        /// <summary>
        /// Create instance of USN journal service
        /// </summary>
        /// <param name="sources"></param>
        /// <param name="snapshot"></param>
        /// <param name="filter"></param>
        /// <param name="lastfilesetid"></param>
        /// <returns></returns>
        private UsnJournalService GetJournalService(IEnumerable <string> sources, ISnapshotService snapshot, IFilter filter, long lastfilesetid)
        {
            if (m_options.UsnStrategy == Options.OptimizationStrategy.Off)
            {
                return(null);
            }

            var journalData = m_database.GetChangeJournalData(lastfilesetid);
            var service     = new UsnJournalService(sources, snapshot, filter, m_options.FileAttributeFilter, m_options.SkipFilesLargerThan,
                                                    journalData, cancellationTokenSource.Token);

            foreach (var volumeData in service.VolumeDataList)
            {
                if (volumeData.IsFullScan)
                {
                    if (volumeData.Exception == null || volumeData.Exception is UsnJournalSoftFailureException)
                    {
                        // soft fail
                        Logging.Log.WriteInformationMessage(LOGTAG, "SkipUsnForVolume",
                                                            "Performing full scan for volume \"{0}\": {1}", volumeData.Volume, volumeData.Exception?.Message);
                    }
                    else
                    {
                        if (m_options.UsnStrategy == Options.OptimizationStrategy.Auto)
                        {
                            Logging.Log.WriteInformationMessage(LOGTAG, "FailedToUseChangeJournal",
                                                                "Failed to use change journal for volume \"{0}\": {1}", volumeData.Volume, volumeData.Exception.Message);
                        }
                        else if (m_options.UsnStrategy == Options.OptimizationStrategy.On)
                        {
                            Logging.Log.WriteWarningMessage(LOGTAG, "FailedToUseChangeJournal", volumeData.Exception,
                                                            "Failed to use change journal for volume \"{0}\": {1}", volumeData.Volume, volumeData.Exception.Message);
                        }
                        else
                        {
                            throw volumeData.Exception;
                        }
                    }
                }
            }

            return(service);
        }
示例#2
0
        /// <summary>
        /// Performs the bulk of work by starting all relevant processes
        /// </summary>
        private static async Task RunMainOperation(IEnumerable <string> sources, Snapshots.ISnapshotService snapshot, UsnJournalService journalService, Backup.BackupDatabase database, Backup.BackupStatsCollector stats, Options options, IFilter sourcefilter, IFilter filter, BackupResults result, Common.ITaskReader taskreader, long lastfilesetid)
        {
            using (new Logging.Timer(LOGTAG, "BackupMainOperation", "BackupMainOperation"))
            {
                // Make sure the CompressionHints table is initialized, otherwise all workers will initialize it
                var tb = options.CompressionHints.Count;

                Task all;
                using (new ChannelScope())
                {
                    all = Task.WhenAll(
                        new []
                    {
                        Backup.DataBlockProcessor.Run(database, options, taskreader),
                        Backup.FileBlockProcessor.Run(snapshot, options, database, stats, taskreader),
                        Backup.StreamBlockSplitter.Run(options, database, taskreader),
                        Backup.FileEnumerationProcess.Run(sources, snapshot, journalService, options.FileAttributeFilter, sourcefilter, filter, options.SymlinkPolicy, options.HardlinkPolicy, options.ExcludeEmptyFolders, options.IgnoreFilenames, options.ChangedFilelist, taskreader),
                        Backup.FilePreFilterProcess.Run(snapshot, options, stats, database),
                        Backup.MetadataPreProcess.Run(snapshot, options, database, lastfilesetid),
                        Backup.SpillCollectorProcess.Run(options, database, taskreader),
                        Backup.ProgressHandler.Run(result)
                    }
                        // Spawn additional block hashers
                        .Union(
                            Enumerable.Range(0, options.ConcurrencyBlockHashers - 1).Select(x => Backup.StreamBlockSplitter.Run(options, database, taskreader))
                            )
                        // Spawn additional compressors
                        .Union(
                            Enumerable.Range(0, options.ConcurrencyCompressors - 1).Select(x => Backup.DataBlockProcessor.Run(database, options, taskreader))
                            )
                        );
                }

                await all.ConfigureAwait(false);

                if (options.ChangedFilelist != null && options.ChangedFilelist.Length >= 1)
                {
                    await database.AppendFilesFromPreviousSetAsync(options.DeletedFilelist);
                }
                else if (journalService != null)
                {
                    // append files from previous fileset, unless part of modifiedSources, which we've just scanned
                    await database.AppendFilesFromPreviousSetWithPredicateAsync((path, fileSize) =>
                    {
                        if (journalService.IsPathEnumerated(path))
                        {
                            return(true);
                        }

                        if (fileSize >= 0)
                        {
                            stats.AddExaminedFile(fileSize);
                        }
                        return(false);
                    });

                    // store journal data in database
                    var data = journalService.VolumeDataList.Where(p => p.JournalData != null).Select(p => p.JournalData).ToList();
                    if (data.Any())
                    {
                        // always record change journal data for current fileset (entry may be dropped later if nothing is uploaded)
                        await database.CreateChangeJournalDataAsync(data);

                        // update the previous fileset's change journal entry to resume at this point in case nothing was backed up
                        await database.UpdateChangeJournalDataAsync(data, lastfilesetid);
                    }
                }

                result.OperationProgressUpdater.UpdatefileCount(result.ExaminedFiles, result.SizeOfExaminedFiles, true);
            }
        }
示例#3
0
        public static Task Run(IEnumerable <string> sources, Snapshots.ISnapshotService snapshot, UsnJournalService journalService, FileAttributes fileAttributes, Duplicati.Library.Utility.IFilter sourcefilter, Duplicati.Library.Utility.IFilter emitfilter, Options.SymlinkStrategy symlinkPolicy, Options.HardlinkStrategy hardlinkPolicy, bool excludeemptyfolders, string[] ignorenames, string[] changedfilelist, ITaskReader taskreader)
        {
            return(AutomationExtensions.RunTask(
                       new
            {
                Output = Backup.Channels.SourcePaths.ForWrite
            },

                       async self =>
            {
                var hardlinkmap = new Dictionary <string, string>();
                var mixinqueue = new Queue <string>();
                Duplicati.Library.Utility.IFilter enumeratefilter = emitfilter;

                bool includes;
                bool excludes;
                Library.Utility.FilterExpression.AnalyzeFilters(emitfilter, out includes, out excludes);
                if (includes && !excludes)
                {
                    enumeratefilter = Library.Utility.FilterExpression.Combine(emitfilter, new Duplicati.Library.Utility.FilterExpression("*" + System.IO.Path.DirectorySeparatorChar, true));
                }

                // Simplify checking for an empty list
                if (ignorenames != null && ignorenames.Length == 0)
                {
                    ignorenames = null;
                }

                // If we have a specific list, use that instead of enumerating the filesystem
                IEnumerable <string> worklist;
                if (changedfilelist != null && changedfilelist.Length > 0)
                {
                    worklist = changedfilelist.Where(x =>
                    {
                        var fa = FileAttributes.Normal;
                        try
                        {
                            fa = snapshot.GetAttributes(x);
                        }
                        catch
                        {
                        }

                        return AttributeFilter(x, fa, snapshot, sourcefilter, hardlinkPolicy, symlinkPolicy, hardlinkmap, fileAttributes, enumeratefilter, ignorenames, mixinqueue);
                    });
                }
                else
                {
                    Library.Utility.Utility.EnumerationFilterDelegate attributeFilter = (root, path, attr) =>
                                                                                        AttributeFilter(path, attr, snapshot, sourcefilter, hardlinkPolicy, symlinkPolicy, hardlinkmap, fileAttributes, enumeratefilter, ignorenames, mixinqueue);

                    if (journalService != null)
                    {
                        // filter sources using USN journal, to obtain a sub-set of files / folders that may have been modified
                        sources = journalService.GetModifiedSources(attributeFilter);
                    }

                    worklist = snapshot.EnumerateFilesAndFolders(sources, attributeFilter, (rootpath, errorpath, ex) =>
                    {
                        Logging.Log.WriteWarningMessage(FILTER_LOGTAG, "FileAccessError", ex, "Error reported while accessing file: {0}", errorpath);
                    });
                }

                var source = ExpandWorkList(worklist, mixinqueue, emitfilter, enumeratefilter);
                if (excludeemptyfolders)
                {
                    source = ExcludeEmptyFolders(source);
                }

                // Process each path, and dequeue the mixins with symlinks as we go
                foreach (var s in source)
                {
                    if (!await taskreader.ProgressAsync)
                    {
                        return;
                    }

                    await self.Output.WriteAsync(s);
                }
            }));
        }
示例#4
0
        public static async Task Run(IEnumerable <string> sources, Snapshots.ISnapshotService snapshot, UsnJournalService journalService, BackupResults result, Options options, IFilter sourcefilter, IFilter filter, Common.ITaskReader taskreader, System.Threading.CancellationToken token)
        {
            // Make sure we create the enumeration process in a separate scope,
            // but keep the log channel from the parent scope
            using (Logging.Log.StartIsolatingScope(true))
                using (new IsolatedChannelScope())
                {
                    var enumeratorTask = Backup.FileEnumerationProcess.Run(sources, snapshot, journalService, options.FileAttributeFilter, sourcefilter, filter, options.SymlinkPolicy, options.HardlinkPolicy, options.ExcludeEmptyFolders, options.IgnoreFilenames, options.ChangedFilelist, taskreader, token);
                    var counterTask    = AutomationExtensions.RunTask(new
                    {
                        Input = Backup.Channels.SourcePaths.ForRead
                    },

                                                                      async self =>
                    {
                        var count = 0L;
                        var size  = 0L;

                        try
                        {
                            while (await taskreader.ProgressAsync && !token.IsCancellationRequested)
                            {
                                var path = await self.Input.ReadAsync();

                                count++;

                                try
                                {
                                    size += snapshot.GetFileSize(path);
                                }
                                catch
                                {
                                }

                                result.OperationProgressUpdater.UpdatefileCount(count, size, false);
                            }
                        }
                        finally
                        {
                            result.OperationProgressUpdater.UpdatefileCount(count, size, true);
                        }
                    });

                    await Task.WhenAll(enumeratorTask, counterTask);
                }
        }