/// <summary> /// Ends the sequence of creating a content/signature pair. /// Writes the list of deleted files to the archives. /// </summary> /// <param name="signaturefile">The signature archive file</param> /// <param name="contentfile">The content archive file</param> /// <param name="volumesize">The max volume size</param> /// <returns>True if the volume is completed, false otherwise</returns> public bool FinalizeMultiPass(Library.Interface.ICompression signaturefile, Library.Interface.ICompression contentfile, long volumesize) { if (!m_finalized) { if (m_unproccesed.Files.Count == 0) { long stringsize = 0; foreach (string s in m_oldSignatures.Keys) { string sourcefolder = "<unknown>"; try { string fullpath = GetFullPathFromRelname(s); sourcefolder = GetSourceFolder(fullpath); if (!m_unproccesed.IsAffectedByError(fullpath)) { m_deletedfiles.Add(s); stringsize += System.Text.Encoding.UTF8.GetByteCount(s + "\r\n"); } } catch (Exception ex) { if (m_stat != null) m_stat.LogError(string.Format(Strings.RSyncDir.DeletedFilenameError, s, sourcefolder), ex); Logging.Log.WriteMessage(string.Format(Strings.RSyncDir.DeletedFilenameError, s, sourcefolder), XervBackup.Library.Logging.LogMessageType.Error, ex); m_unproccesed.FilesWithError.Add(s); } } m_oldSignatures.Clear(); if (m_deletedfiles.Count > 0) { //The +100 is a safety margin stringsize += System.Text.Encoding.UTF8.GetByteCount(DELETED_FILES) + 100; if (contentfile.Size + contentfile.FlushBufferSize + stringsize > volumesize) return false; //The followup cannot fit in the volume, so we make a full new volume signaturefile.WriteAllLines(DELETED_FILES, m_deletedfiles.ToArray()); contentfile.WriteAllLines(DELETED_FILES, m_deletedfiles.ToArray()); m_deletedfiles.Clear(); } //We only write the USN if all files were processed if (m_currentUSN != null) using (System.IO.Stream s = signaturefile.CreateFile(USN_VALUES)) m_currentUSN.Save(s); //Only write this if all files were processed if (m_checkedUnchangedFiles.Count > 0) signaturefile.WriteAllLines(UNMODIFIED_FILES, m_checkedUnchangedFiles.ToArray()); if (m_unproccesed.Symlinks.Count > 0) { foreach(KeyValuePair<string, string> kvp in m_unproccesed.Symlinks) { string target = FilenamesToPlatformIndependant(new string[] { kvp.Value })[0]; string source = Path.Combine(SYMLINK_ROOT, GetRelativeName(kvp.Key)); byte[] targetBytes = Encoding.UTF8.GetBytes(target); contentfile.WriteAllBytes(source, targetBytes); signaturefile.WriteAllBytes(source, targetBytes); } m_unproccesed.Symlinks.Clear(); } } m_finalized = true; } return m_finalized; }