Example #1
0
        }         // proc UpdateMetaData

        protected override void ProcessRecord()
        {
            var notify     = new CmdletNotify(this);
            var totalBytes = 0L;

            // Lese den Index ein
            var index = new FileIndex();

            index.ReadIndex(notify, Path.Combine(Source, "index.txt.gz"));

            // Suche alle aktiven Archive
            var archives = new Dictionary <string, List <FileIndexItem> >(StringComparer.OrdinalIgnoreCase);

            using (var bar = notify.CreateStatus("Wiederherstellen eines Verzeichnisses", $"Wiederherstellen von {Source}..."))
            {
                var filter = new FileFilterRules(Filter);                 // Erzeuge Filter und entferne alle Dateien aus dem Index die dem nicht entsprechen
                if (filter.IsEmpty)
                {
                    foreach (var c in index)
                    {
                        AddArchive(archives, c, ref totalBytes);
                    }
                }
                else
                {
                    var remove = new List <FileIndexItem>();
                    foreach (var c in index)
                    {
                        if (filter.IsFiltered(c.RelativePath))
                        {
                            AddArchive(archives, c, ref totalBytes);
                        }
                        else
                        {
                            remove.Add(c);
                        }
                    }

                    foreach (var c in remove)
                    {
                        index.RemoveEntry(c);
                    }
                }

                // Entpacke die Archvie
                bar.StartRemaining();
                bar.Maximum = totalBytes;

                foreach (var c in archives)
                {
                    if (Stuff.IsGZipFile(c.Key) || Stuff.IsNoPackFile(c.Key))                     // GZip-Datei
                    {
                        using (var src = Stuff.OpenRead(new FileInfo(Path.Combine(Source, c.Key)), notify, CompressMode.Auto))
                        {
                            var srcFile = c.Value[0];
                            var dstFile = new FileInfo(Path.Combine(Target, srcFile.RelativePath));
                            using (var dst = Override ? Stuff.OpenWrite(dstFile, notify) : Stuff.OpenCreate(dstFile, notify))
                            {
                                dst.SetLength(srcFile.Length);
                                Stuff.CopyRawBytes(bar, srcFile.RelativePath, srcFile.Length, src, dst);
                            }

                            // Aktualisiere die Attribute
                            UpdateMetaData(notify, srcFile, dstFile);
                        }
                    }
                    else                     // zip-Datei
                    {
                        using (var zipStream = Stuff.OpenRead(new FileInfo(Path.Combine(Source, c.Key)), notify, CompressMode.Stored))
                            using (var zip = new ZipInputStream(zipStream))
                            {
                                var srcEntry = zip.GetNextEntry();
                                while (srcEntry != null)
                                {
                                    // Suche den passenden Index
                                    var srcIndex = c.Value.Find(c2 => String.Compare(srcEntry.Name, ZipEntry.CleanName(c2.RelativePath), StringComparison.OrdinalIgnoreCase) == 0);
                                    if (srcIndex != null)
                                    {
                                        var dstFile = new FileInfo(Path.Combine(Target, srcIndex.RelativePath));
                                        using (var dst = Override ? Stuff.OpenWrite(dstFile, notify) : Stuff.OpenCreate(dstFile, notify))
                                        {
                                            dst.SetLength(srcIndex.Length);
                                            Stuff.CopyRawBytes(bar, srcIndex.RelativePath, srcIndex.Length, zip, dst);
                                        }

                                        // Aktualisiere die Attribute
                                        UpdateMetaData(notify, srcIndex, dstFile);
                                    }
                                    else
                                    {
                                        zip.CloseEntry();
                                    }

                                    // Schließe den Eintrag ab
                                    srcEntry = zip.GetNextEntry();
                                }
                            }
                    }
                }
            }
        }         // 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