} // func CompareDirectoryRoot #endregion protected override void ProcessRecord() { using (bar = Notify.CreateStatus(String.Format("Synchronize {0} -> {1}", Source, Target), String.Empty)) { bar.Maximum = 0; // start compare var t = Task.Factory.StartNew(CompareDirectoryRoot); // copy files bar.StartRemaining(); DequeueActions(true); if (!Stopping) { try { t.Wait(); } catch (AggregateException e) { WriteError(new ErrorRecord(e.InnerException, "1", ErrorCategory.OperationStopped, this)); throw; } } } } // proc ProcessRecord
} // proc DeleteSafe protected override void ProcessRecord() { directoriesDeleted = 0; filesDeleted = 0; bytesDeleted = 0; using (var bar = Notify.CreateStatus("Clean directory", $"Clean {Target}...")) CleanDirectoryPath(bar, DateTime.Now, Age.TotalMilliseconds > 0 ? Age : Age.Negate(), new DirectoryInfo(Target), String.Empty); WriteVerbose($"Removed: {directoriesDeleted:N0} directories, {filesDeleted:N0} files, {Stuff.FormatFileSize(bytesDeleted)}"); } // proc ProcessRecord
protected override void ProcessRecord() { using (var con = new SqlConnection(Connection)) using (var bar = Notify.CreateStatus($"Backup database {con.Database}...", "Verbinde...")) { progress = bar; con.Open(); con.InfoMessage += Con_InfoMessage; // get index information using (var cmd = con.CreateCommand()) { cmd.CommandTimeout = 0; var indexTasks = new List <Tuple <string, string> >(); bar.StatusDescription = $"Check indizes..."; cmd.CommandText = String.Format(String.Join(Environment.NewLine, "SELECT s.[name], o.[name], i.[name], avg_fragmentation_in_percent, fragment_count", " FROM sys.dm_db_index_physical_stats(DB_ID(N'{0}'), NULL, NULL, NULL, NULL) AS f", " INNER JOIN sys.indexes AS i ON(f.object_id = i.object_id AND f.index_id = i.index_id)", " INNER JOIN sys.objects AS o ON(i.object_id = o.object_id)", " INNER JOIN sys.schemas s on(o.schema_id = s.schema_id)"), con.Database ); using (var r = cmd.ExecuteReader()) { while (r.Read()) { var schemaName = r.GetString(0); var tableName = r.GetString(1); var indexName = r.GetString(2); var frag = r.GetDouble(3); var fragCount = r.IsDBNull(4) ? 0 : r.GetInt64(4); var action = frag >= 5.0f && frag < 30.0 ? "REORGANIZE" : frag >= 30.0f ? "REBUILD" : null; if (action != null) { indexTasks.Add( new Tuple <string, string>( $"Index {indexName} of {schemaName}.{tableName} - {action} (fragmentation: {frag:N1})...", $"ALTER INDEX [{indexName}] ON [{schemaName}].[{tableName}] {action}" ) ); } } } // check indizes if (indexTasks.Count > 0) { bar.Maximum = indexTasks.Count; for (var i = 0; i < indexTasks.Count; i++) { bar.Position = i; bar.CurrentOperation = indexTasks[i].Item1; cmd.CommandText = indexTasks[i].Item2; cmd.ExecuteNonQuery(); } } bar.CurrentOperation = null; // do backup bar.StatusDescription = $"Execute Backup..."; cmd.CommandText = String.Format(String.Join(Environment.NewLine, "BACKUP DATABASE [{0}]", "TO DISK = N'{1}' WITH NOFORMAT, INIT, ", "NAME = N'{0}-Vollständig Datenbank Sichern', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, ", "STATS = 1, CHECKSUM" ), con.Database, BackupFile ); bar.Maximum = 100; bar.StartRemaining(); cmd.ExecuteScalar(); // ExecuteNonQuery does not fire InfoMessage bar.StopRemaining(); // check backup state bar.StatusDescription = $"Check Backup..."; cmd.CommandText = String.Format("select position from msdb..backupset where database_name = N'{0}' and backup_set_id = (select max(backup_set_id) from msdb..backupset where database_name = N'{0}')", con.Database); var pos = cmd.ExecuteScalar(); if (pos is DBNull) { throw new Exception("Backup information not found."); } // verify backup bar.StatusDescription = $"Verify Backup..."; cmd.CommandText = String.Format("RESTORE VERIFYONLY FROM DISK = N'{0}' WITH FILE = {1}, NOUNLOAD, NOREWIND", BackupFile, pos); cmd.ExecuteScalar(); } } } // proc ProcessRecord
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