protected override void ProcessRecord()
        {
            var index = new FileIndex();

            foreach (var item in Items)
            {
                index.UpdateFile(item);
            }

            index.WriteIndex(Notify, Index);
        }         // proc ProcessRecord
Example #2
0
        protected override void ProcessRecord()
        {
            const string zipArchivePlaceHolder = "#";

            using (var bar = Notify.CreateStatus("Erzeuge Backup", $"Sicherung von {Source}..."))
            {
                var totalBytes = 0L;
                //var position = 0L;
                var itemsModified   = 0;
                var itemsUnmodified = 0;
                var itemsZipped     = 0;
                var archiveUsed     = new Dictionary <string, int>(StringComparer.OrdinalIgnoreCase);

                // Lade Index-Datei
                bar.StatusDescription = "Lese Index...";
                var targetPath  = new DirectoryInfo(Target);
                var targetIndex = Path.Combine(targetPath.FullName, "index.txt.gz");
                var index       = new FileIndex();
                if (String.IsNullOrEmpty(ShadowIndex))                 // Kein lokaler Index, also lade dem vom Target
                {
                    index.ReadIndex(Notify, targetIndex);
                }
                else
                {
                    index.ReadIndex(Notify, ShadowIndex);
                }

                // Gleiche die Daten ab und erzeuge die Statistik
                bar.StatusDescription = "Vergleiche Dateien mit Index...";
                var swFileStopWatch = Stopwatch.StartNew();
                var files           = new FileList(Notify, new DirectoryInfo(Source), Excludes);
                foreach (var c in files)
                {
                    var indexItem = index.UpdateFile(c);
                    var tmp       = 0;

                    // Gib einen zwischen Bericht
                    if (swFileStopWatch.ElapsedMilliseconds > 500)
                    {
                        bar.StatusDescription = $"Vergleiche {c.RelativePath} mit Index...";
                        swFileStopWatch       = Stopwatch.StartNew();
                    }

                    switch (indexItem.State)
                    {
                    case FileIndexState.Modified:
                        // Erzeuge den Eintrag im Index
                        if (c.FileInfo.Length < ZipArchiveBorder)
                        {
                            itemsZipped++;
                            indexItem.ArchiveName = zipArchivePlaceHolder;
                        }
                        else
                        {
                            if (String.IsNullOrEmpty(indexItem.ArchiveName))
                            {
                                indexItem.ArchiveName = Guid.NewGuid().ToString("N") + Path.GetExtension(indexItem.RelativePath) + (ZipFile(indexItem.RelativePath) ? ".gz" : ".nopack");
                            }
                        }

                        // Statistik für den Progress
                        totalBytes += c.FileInfo.Length;
                        itemsModified++;

                        // Erhöhe den Zugriff
                        if (archiveUsed.TryGetValue(indexItem.ArchiveName, out tmp))
                        {
                            archiveUsed[indexItem.ArchiveName] = tmp + 1;
                        }
                        break;

                    case FileIndexState.Unmodified:
                        // Prüfe die existens den Archives
                        if (Force || (String.IsNullOrEmpty(ShadowIndex) && !File.Exists(Path.Combine(targetPath.FullName, indexItem.ArchiveName))))
                        {
                            indexItem.Update(c.FileInfo);
                            goto case FileIndexState.Modified;
                        }
                        itemsUnmodified++;

                        // Erhöhe den Zugriff
                        if (archiveUsed.TryGetValue(indexItem.ArchiveName, out tmp))
                        {
                            archiveUsed[indexItem.ArchiveName] = tmp + 1;
                        }
                        break;

                    case FileIndexState.None:
                        if (archiveUsed.ContainsKey(indexItem.ArchiveName))
                        {
                            archiveUsed[indexItem.ArchiveName] = 0;
                        }
                        break;
                    }
                }

                // Schreibe das neue Archiv
                if (itemsModified > 0)
                {
                    string          currentArchiveName = null;
                    FileWrite       zipStream          = null;
                    ZipOutputStream zip = null;
                    try
                    {
                        bar.StartRemaining();
                        bar.Maximum = totalBytes;

                        var removeItems = new List <FileIndexItem>();
                        foreach (var c in index)
                        {
                            switch (c.State)
                            {
                            case FileIndexState.Modified:                                     // Kopiere die Datei
                                using (var src = Stuff.OpenRead(new FileInfo(Path.Combine(Source, c.RelativePath)), Notify, allowEmpty: true))
                                {
                                    if (c.ArchiveName == zipArchivePlaceHolder)
                                    {
                                        // Schließe das Archiv, wenn genug Inhalt
                                        if (zipStream != null && zipStream.Stream.Position > 512 << 20)
                                        {
                                            zipStream.Commit();
                                            CloseZipStream(zipStream, zip);
                                            currentArchiveName = null;
                                        }

                                        // Erzeuge das Archiv
                                        if (currentArchiveName == null)
                                        {
                                            currentArchiveName = Guid.NewGuid().ToString("N") + ".zip";
                                            CreateZipStream(targetPath, currentArchiveName, out zipStream, out zip);
                                        }

                                        // Kopiere die Daten
                                        ZipFileItem(Notify, bar, src, zip, c);
                                        c.ArchiveName = currentArchiveName;
                                    }
                                    else
                                    {
                                        GZipFileItem(Notify, bar, src, targetPath, c);
                                    }
                                }
                                break;

                            case FileIndexState.None:                                     // Lösche den Index
                                removeItems.Remove(c);
                                break;
                            }
                        }

                        // Entferne die Einträge aus dem Index
                        foreach (var c in removeItems)
                        {
                            index.RemoveEntry(c);
                        }

                        if (zipStream != null)
                        {
                            zipStream.Commit();
                        }
                    }
                    finally
                    {
                        CloseZipStream(zipStream, zip);
                    }

                    // Schreibe den Index
                    bar.StopRemaining();
                    bar.StatusDescription = "Schreibe Index...";
                    if (!String.IsNullOrEmpty(ShadowIndex))
                    {
                        index.WriteIndex(Notify, ShadowIndex);
                    }
                    index.WriteIndex(Notify, targetIndex);

                    // Lösche ungenutzte Archive
                    if (String.IsNullOrEmpty(ShadowIndex))
                    {
                        foreach (var c in archiveUsed)
                        {
                            if (c.Value == 0)
                            {
                                var file = new FileInfo(Path.Combine(targetPath.FullName, c.Key));
                                bar.StatusDescription = $"Nicht mehr benötigtes Archiv '{c.Key}'...";
                                Notify.SafeIO(file.Delete, bar.StatusDescription);
                            }
                        }
                    }
                    else                     // Erzeuge nur eine Löschdatei
                    {
                        bar.StatusDescription = "Nicht mehr benötigte Archive werden gelöscht...";
                        using (var sw = new StreamWriter(Stuff.OpenWrite(new FileInfo(Path.Combine(targetPath.FullName, "index_rm.txt")), Notify, CompressMode.Stored)))
                        {
                            sw.BaseStream.Position = sw.BaseStream.Length;
                            foreach (var c in archiveUsed)
                            {
                                if (c.Value == 0)
                                {
                                    sw.WriteLine(c.Key);
                                }
                            }
                        }
                    }
                }
            }
        }         // proc ProcessRecord