/// <summary> /// Constructs a new BackendWrapper /// </summary> /// <param name="statistics">The statistics logging module, may be null</param> /// <param name="backend">The url to the backend to wrap</param> /// <param name="options">A set of backend options</param> public BackendWrapper(CommunicationStatistics statistics, string backend, Options options) { m_statistics = statistics; m_options = options; m_filenamestrategy = new FilenameStrategy(m_options); m_backendUrl = backend; m_backend = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(backend, m_options.RawOptions); if (m_backend == null) throw new Exception(string.Format(Strings.BackendWrapper.BackendNotFoundError, backend)); m_reuse_backend = !m_options.NoConnectionReuse; m_first_backend_use = true; m_backendSupportsCreateFolder = m_backend is Library.Interface.IBackend_v2; if (m_options.AutoCleanup) m_orphans = new List<BackupEntryBase>(); if (!string.IsNullOrEmpty(m_options.SignatureCachePath) && !System.IO.Directory.Exists(m_options.SignatureCachePath)) System.IO.Directory.CreateDirectory(m_options.SignatureCachePath); if (!string.IsNullOrEmpty(m_options.Backendlogdatabase)) { m_backendInterfaceLogger = new StateVerification.StateDatabase(m_options.Backendlogdatabase, statistics); m_backendInterfaceLogger.BeginOperation(m_options.MainAction.ToString()); } m_async = m_options.AsynchronousUpload; if (m_async) { //If we are using async operations, the entire class is actually threadsafe, //utilizing a common exclusive lock on all operations. But the implementation does //not prevent starvation, so it should not be called by multiple threads. m_pendingOperations = new Queue<KeyValuePair<BackupEntryBase, string>>(); m_asyncItemProcessed = new System.Threading.AutoResetEvent(false); m_asyncItemReady = new System.Threading.AutoResetEvent(false); m_workerThread = new System.Threading.Thread(ProcessQueue); m_workerThread.Name = "AsyncUploaderThread"; m_queuelock = new object(); m_workerThread.Start(); } }
internal VerificationFile(IEnumerable<ManifestEntry> parentChain, FilenameStrategy str) { m_doc = new System.Xml.XmlDocument(); System.Xml.XmlNode root = m_doc.AppendChild(m_doc.CreateElement("Verify")); root.Attributes.Append(m_doc.CreateAttribute("hash-algorithm")).Value = Utility.Utility.HashAlgorithm; root.Attributes.Append(m_doc.CreateAttribute("version")).Value = "1"; m_node = root.AppendChild(m_doc.CreateElement("Files")); foreach (ManifestEntry mfe in parentChain) { System.Xml.XmlNode f = m_node.AppendChild(m_doc.CreateElement("File")); f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "manifest"; f.Attributes.Append(m_doc.CreateAttribute("name")).Value = mfe.Filename; f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.Filesize.ToString(); f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.RemoteHash)); for (int i = 0; i < mfe.ParsedManifest.SignatureHashes.Count; i++) { string sigfilename = mfe.ParsedManifest.SignatureHashes[i].Name; string contentfilename = mfe.ParsedManifest.ContentHashes[i].Name; bool missing = i >= mfe.Volumes.Count; if (string.IsNullOrEmpty(sigfilename) || string.IsNullOrEmpty(contentfilename)) { if (missing) { sigfilename = str.GenerateFilename(new SignatureEntry(mfe.Time, mfe.IsFull, i + 1)); contentfilename = str.GenerateFilename(new ContentEntry(mfe.Time, mfe.IsFull, i + 1)); //Since these files are missing, we have to guess what their real names were string compressionGuess; if (mfe.Volumes.Count <= 0) compressionGuess = ".zip"; //Default if we have no knowledge else compressionGuess = "." + mfe.Volumes[0].Key.Compression; //Most likely the same as all the others //Encryption will likely be the same as the one the manifest uses string encryptionGuess = string.IsNullOrEmpty(mfe.EncryptionMode) ? "" : "." + mfe.EncryptionMode; sigfilename += compressionGuess + encryptionGuess; contentfilename += compressionGuess + encryptionGuess; } else { sigfilename = mfe.Volumes[i].Key.Filename; contentfilename = mfe.Volumes[i].Value.Filename; } } f = m_node.AppendChild(m_doc.CreateElement("File")); f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "signature"; f.Attributes.Append(m_doc.CreateAttribute("name")).Value = sigfilename; f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.ParsedManifest.SignatureHashes[i].Size.ToString(); if (missing) f.Attributes.Append(m_doc.CreateAttribute("missing")).Value = "true"; f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.ParsedManifest.SignatureHashes[i].Hash)); f = m_node.AppendChild(m_doc.CreateElement("File")); f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "content"; f.Attributes.Append(m_doc.CreateAttribute("name")).Value = contentfilename; f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.ParsedManifest.ContentHashes[i].Size.ToString(); if (missing) f.Attributes.Append(m_doc.CreateAttribute("missing")).Value = "true"; f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.ParsedManifest.ContentHashes[i].Hash)); } } }