private void SetUp(long length) { this.transmission = new Transmission(TransmissionType.DOWNLOAD_NEW_FILE, "testfile"); this.transmission.AddDefaultConstraints(); if (this.localFileStream != null) { this.localFileStream.Dispose(); } this.localFileStream = new MemoryStream(); if (this.hashAlg != null) { this.hashAlg.Dispose(); } this.hashAlg = new SHA1Managed(); this.remoteLength = length; this.remoteContent = new byte[this.remoteLength]; if (this.random != null) { this.random.Dispose(); } this.random = RandomNumberGenerator.Create(); this.random.GetBytes(this.remoteContent); this.mockedMemStream = new Mock<MemoryStream>(this.remoteContent) { CallBase = true }; this.mockedStream = new Mock<IContentStream>(); this.mockedStream.Setup(stream => stream.Length).Returns(this.remoteLength); this.mockedStream.Setup(stream => stream.Stream).Returns(this.mockedMemStream.Object); this.mockedDocument = new Mock<IDocument>(); this.mockedDocument.Setup(doc => doc.ContentStreamLength).Returns(this.remoteLength); this.mockedDocument.Setup(doc => doc.GetContentStream()).Returns(this.mockedStream.Object); }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <param name="update">Not or not yet used</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { { byte[] buffer = new byte[8 * 1024]; int len; while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long? fileLength = remoteDocument.ContentStreamLength; // Download content if exists if (fileLength > 0) { long offset = localFileStream.Position; long remainingBytes = (fileLength != null) ? (long)fileLength - offset : this.ChunkSize; try { do { offset += this.DownloadNextChunk(remoteDocument, offset, remainingBytes, transmission, localFileStream, hashAlg); } while(fileLength == null); } catch (DotCMIS.Exceptions.CmisConstraintException) { } } else { transmission.Position = 0; transmission.Length = 0; } hashAlg.TransformFinalBlock(new byte[0], 0, 0); }
public void UploadWhileAnotherProcessIsWritingToFile() { var fileName = "slowFile.txt"; var chunkSize = 1024; var chunks = 100; byte[] chunk = new byte[chunkSize]; var finalLength = chunks * chunkSize; var file = new FileInfo(Path.Combine(this.LocalTestDir.FullName, fileName)); var mockedDocument = new Mock<IDocument>(); var transmissionStatus = new Transmission(TransmissionType.UPLOAD_NEW_FILE, fileName); mockedDocument.Setup(doc => doc.Name).Returns(fileName); using (var remoteStream = new MemoryStream()) { mockedDocument.Setup(doc => doc.SetContentStream(It.IsAny<IContentStream>(), It.Is<bool>(b => b == true), It.Is<bool>(b => b == true))) .Callback<IContentStream, bool, bool>((s, b, r) => s.Stream.CopyTo(remoteStream)) .Returns(new Mock<IObjectId>().Object); using (var fileStream = file.Open(FileMode.CreateNew, FileAccess.Write, FileShare.Read)) { using (var task = Task.Factory.StartNew(() => { var newFileHandle = new FileInfo(file.FullName); using (var hashAlg = new SHA1Managed()) using (var readingFileStream = newFileHandle.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var uploader = new SimpleFileUploader()) { uploader.UploadFile(mockedDocument.Object, readingFileStream, transmissionStatus, hashAlg); } Assert.That(remoteStream.Length, Is.EqualTo(finalLength)); })) { for (int i = 0; i < chunks; i++) { Thread.Sleep(10); fileStream.Write(chunk, 0, chunkSize); } task.Wait(); } } } }
public void ConstructorTakesTypeFileNameAndCachePath(TransmissionType type) { var underTest = new Transmission(type, this.path, this.cache); Assert.That(underTest.Type, Is.EqualTo(type)); Assert.That(underTest.Path, Is.EqualTo(this.path)); Assert.That(underTest.CachePath, Is.EqualTo(this.cache)); Assert.That(underTest.Status, Is.EqualTo(TransmissionStatus.TRANSMITTING)); }
public void Percent(TransmissionType type) { var underTest = new Transmission(type, this.path); double? percent = null; underTest.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) => { if (e.PropertyName == Utils.NameOf((Transmission t) => t.Percent)) { percent = (sender as Transmission).Percent; } }; Assert.That(underTest.Percent, Is.Null); underTest.Length = 100; underTest.Position = 0; Assert.That(percent, Is.EqualTo(0)); underTest.Position = 10; Assert.That(percent, Is.EqualTo(10)); underTest.Position = 100; Assert.That(percent, Is.EqualTo(100)); underTest.Length = 1000; Assert.That(percent, Is.EqualTo(10)); underTest.Position = 1000; underTest.Length = 2000; Assert.That(percent, Is.EqualTo(50)); underTest.Position = 201; underTest.Length = 1000; Assert.That(percent, Is.EqualTo(20)); }
/// <summary> /// Uploads the file. /// Resumes an upload if the given localFileStream.Position is larger than zero. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException"> /// Contains the last successful remote document state. This is needed for continue a failed upload. /// </exception> public override IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { IDocument result = remoteDocument; for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) { bool isFirstChunk = offset == 0; bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length; using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize)) using (var offsetstream = new OffsetStream(chunkstream, offset)) using (var transmissionStream = transmission.CreateStream(offsetstream)) { transmission.Length = localFileStream.Length; transmission.Position = offset; chunkstream.ChunkPosition = offset; ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name); if (isLastChunk) { contentStream.Length = localFileStream.Length - offset; } else { contentStream.Length = this.ChunkSize; } contentStream.Stream = transmissionStream; try { if (isFirstChunk && result.ContentStreamId != null && overwrite) { result.DeleteContentStream(true); } result.AppendContentStream(contentStream, isLastChunk, true); HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) { hash.TransformFinalBlock(new byte[0], 0, 0); update(hash.Hash, result.ContentStreamLength.GetValueOrDefault()); } } } catch (Exception e) { if (e is FileTransmission.AbortException) { throw; } if (e.InnerException is FileTransmission.AbortException) { throw e.InnerException; } throw new UploadFailedException(e, result); } } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return result; }
public void SetUp() { this.transmission = new Transmission(TransmissionType.UPLOAD_NEW_FILE, "testfile"); this.transmission.AddDefaultConstraints(); this.fileLength = 1024 * 1024; this.localContent = new byte[this.fileLength]; if (this.localFileStream != null) { this.localFileStream.Dispose(); } this.localFileStream = new MemoryStream(this.localContent); if (this.hashAlg != null) { this.hashAlg.Dispose(); } this.hashAlg = new SHA1Managed(); using (RandomNumberGenerator random = RandomNumberGenerator.Create()) { random.GetBytes(this.localContent); } this.mockedMemStream = new Mock<MemoryStream>() { CallBase = true }; this.mockedDocument = new Mock<IDocument>(); this.mockedStream = new Mock<IContentStream>(); this.mockedStream.Setup(stream => stream.Length).Returns(this.fileLength); this.mockedStream.Setup(stream => stream.Stream).Returns(this.mockedMemStream.Object); this.mockedDocument.Setup(doc => doc.Name).Returns("test.txt"); }
private void HandleDeleteTransmissionEvent(Transmission item) { lock (lockTransmissionItems) { for (int i = TransmissionItems.Count - 1; i >= 0; --i) { if (TransmissionItems[i].Path == item.Path) { TransmissionItems.RemoveAt(i); changeAll = true; return; } } } }
public void AbortWriteIfAbortIsCalled() { var transmission = new Transmission(TransmissionType.DOWNLOAD_MODIFIED_FILE, "path"); using (var inputStream = new MemoryStream(new byte[1024 * 1024 * 10])) using (var stream = new Mock<MemoryStream>() { CallBase = true }.Object) using (var underTest = new TransmissionStream(stream, transmission)) { transmission.Abort(); Assert.Throws<AbortException>(() => inputStream.CopyTo(underTest)); Mock.Get(stream).Verify(s => s.WriteByte(It.IsAny<byte>()), Times.Never()); Mock.Get(stream).Verify(s => s.Write(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never()); } }
public void AbortReadIfAbortIsCalled() { var transmission = new Transmission(TransmissionType.DOWNLOAD_MODIFIED_FILE, "path"); byte[] content = new byte[1024]; using (var outputStream = new MemoryStream()) using (var stream = new Mock<MemoryStream>() { CallBase = true }.Object) using (var underTest = new TransmissionStream(stream, transmission)) { transmission.Abort(); Assert.Throws<AbortException>(() => underTest.CopyTo(outputStream)); Mock.Get(stream).Verify(s => s.ReadByte(), Times.Never()); Mock.Get(stream).Verify(s => s.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never()); } }
/// <summary> /// Creates a new the transmission object and adds it to the manager. The manager decides when to and how the /// transmission gets removed from it. /// </summary> /// <returns>The transmission.</returns> /// <param name="type">Transmission type.</param> /// <param name="path">Full path.</param> /// <param name="cachePath">Cache path.</param> public Transmission CreateTransmission(TransmissionType type, string path, string cachePath = null) { var transmission = new Transmission(type, path, cachePath); lock (this.collectionLock) { var entry = this.pathToRepoNameMapping.FirstOrDefault(t => path.StartsWith(t.Key)); transmission.Repository = entry.Value ?? string.Empty; if (entry.Key != null) { transmission.RelativePath = path.Substring(entry.Key.Length).TrimStart(System.IO.Path.DirectorySeparatorChar); } transmission.PropertyChanged += this.TransmissionFinished; this.activeTransmissions.Add(transmission); } return transmission; }
/// <summary> /// Initializes a new instance of the <see cref="CmisSync.Lib.Streams.TransmissionStream"/> class. /// </summary> /// <param name="wrappedStream">Wrapped stream.</param> /// <param name="transmission">Transmission object to be notified about changes and listened to events as well.</param> public TransmissionStream(Stream wrappedStream, Transmission transmission) { if (transmission == null) { throw new ArgumentNullException("transmission"); } this.abort = new AbortableStream(wrappedStream); this.pause = new PausableStream(this.abort); this.bandwidthNotify = new BandwidthNotifyingStream(this.pause); this.progress = new ProgressStream(this.bandwidthNotify); this.abort.PropertyChanged += (object sender, PropertyChangedEventArgs e) => { var a = sender as AbortableStream; if (e.PropertyName == Utils.NameOf(() => a.Exception)) { transmission.Status = TransmissionStatus.ABORTED; transmission.FailedException = a.Exception; } }; this.bandwidthNotify.PropertyChanged += (object sender, PropertyChangedEventArgs e) => { var s = sender as BandwidthNotifyingStream; if (e.PropertyName == Utils.NameOf(() => s.BitsPerSecond)) { transmission.BitsPerSecond = s.BitsPerSecond; } }; this.progress.PropertyChanged += (object sender, PropertyChangedEventArgs e) => { var p = sender as ProgressStream; if (e.PropertyName == Utils.NameOf(() => p.Position)) { transmission.Position = p.Position; } else if (e.PropertyName == Utils.NameOf(() => p.Length)) { transmission.Length = p.Length; } }; transmission.PropertyChanged += (object sender, PropertyChangedEventArgs e) => { var t = sender as Transmission; if (e.PropertyName == Utils.NameOf(() => t.Status)) { if (t.Status == TransmissionStatus.ABORTING) { this.abort.Abort(); this.pause.Resume(); } else if (t.Status == TransmissionStatus.PAUSED) { this.pause.Pause(); } else if (t.Status == TransmissionStatus.TRANSMITTING) { this.pause.Resume(); } } }; if (transmission.Status == TransmissionStatus.ABORTING || transmission.Status == TransmissionStatus.ABORTED) { this.abort.Abort(); } }
public void NotifyLengthChange(TransmissionType type) { var underTest = new Transmission(type, this.path); long expectedLength = 0; int lengthChanged = 0; underTest.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) => { if (e.PropertyName == Utils.NameOf((Transmission t) => t.Length)) { Assert.That((sender as Transmission).Length, Is.EqualTo(expectedLength)); lengthChanged++; } }; underTest.Length = expectedLength; underTest.Length = expectedLength; Assert.That(lengthChanged, Is.EqualTo(1)); expectedLength = 1024; underTest.Length = expectedLength; Assert.That(lengthChanged, Is.EqualTo(2)); }
private void HandleUpdateTransmissionEvent(Transmission item) { lock (lockTransmissionItems) { for (int i = 0; i < TransmissionItems.Count; ++i) { if (TransmissionItems[i].Path == item.Path) { TransmissionItems[i] = item; if (item.Done) { // finished TransmissionItem should put to the tail if (i < TransmissionItems.Count - 1 && !TransmissionItems[i + 1].Done) { TransmissionItems[i] = TransmissionItems[i + 1]; TransmissionItems[i + 1] = item; changeAll = true; continue; } } return; } } } }
/// <summary> /// Uploads the localFileStream to remoteDocument. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException">If upload fails</exception> public virtual IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { if (remoteDocument == null) { throw new ArgumentException("remoteDocument can not be null"); } if (localFileStream == null) { throw new ArgumentException("localFileStream can not be null"); } if (transmission == null) { throw new ArgumentException("status can not be null"); } if (hashAlg == null) { throw new ArgumentException("hashAlg can not be null"); } using(NonClosingHashStream hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using(var transmissionStream = transmission.CreateStream(hashstream)) { ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(contentStream.FileName); contentStream.Stream = transmissionStream; try { remoteDocument.SetContentStream(contentStream, overwrite, true); } catch(Exception e) { throw new UploadFailedException(e, remoteDocument); } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return remoteDocument; }
public void SetUp() { this.transmission = new Transmission(TransmissionType.UPLOAD_NEW_FILE, "testfile"); this.transmission.AddDefaultConstraints(); this.lastChunk = 0; this.localContent = new byte[this.fileLength]; if (this.localFileStream != null) { this.localFileStream.Dispose(); } this.localFileStream = new MemoryStream(this.localContent); if (this.hashAlg != null) { this.hashAlg.Dispose(); } this.hashAlg = new SHA1Managed(); using (RandomNumberGenerator random = RandomNumberGenerator.Create()) { random.GetBytes(this.localContent); } if (this.remoteStream != null) { this.remoteStream.Dispose(); } this.remoteStream = new MemoryStream(); this.mockedDocument = new Mock<IDocument>(); this.mockedStream = new Mock<IContentStream>(); this.returnedObjectId = new Mock<IObjectId>(); this.mockedStream.Setup(stream => stream.Length).Returns(this.fileLength); this.mockedStream.Setup(stream => stream.Stream).Returns(this.remoteStream); this.mockedDocument.Setup(doc => doc.Name).Returns("test.txt"); this.mockedDocument.Setup(doc => doc.AppendContentStream(It.IsAny<IContentStream>(), It.Is<bool>(b => b == true), It.Is<bool>(b => b == true))) .Callback<IContentStream, bool, bool>((s, b, r) => s.Stream.CopyTo(this.remoteStream)) .Returns(this.returnedObjectId.Object) .Callback(() => this.lastChunk++); this.mockedDocument.Setup(doc => doc.AppendContentStream(It.IsAny<IContentStream>(), It.Is<bool>(b => b == false), It.Is<bool>(b => b == true))) .Callback<IContentStream, bool, bool>((s, b, r) => s.Stream.CopyTo(this.remoteStream)) .Returns(this.returnedObjectId.Object); }
public void SetUp() { this.transmission = new Transmission(TransmissionType.DOWNLOAD_NEW_FILE, "testfile"); this.transmission.AddDefaultConstraints(); if (this.localFileStream != null) { this.localFileStream.Dispose(); } this.localFileStream = new MemoryStream(); if (this.hashAlg != null) { this.hashAlg.Dispose(); } this.hashAlg = new SHA1CryptoServiceProvider(); this.remoteContent = new byte[this.remoteLength]; using (var random = RandomNumberGenerator.Create()) { random.GetBytes(this.remoteContent); } this.mock = new Mock<IDocument>(); this.mockedStream = new Mock<IContentStream>(); this.localFile = Path.GetTempFileName(); }
/// <summary> /// Appends the localFileStream to the remoteDocument. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be appended to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='status'> /// Transmission status where the uploader should report its appending status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the appended content. /// </param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException">If Upload fails</exception> public virtual IDocument AppendFile(IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg) { using (var transmissionStream = transmission.CreateStream(localFileStream)) using (var hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Read)) { ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(contentStream.FileName); contentStream.Stream = hashstream; try { return(remoteDocument.AppendContentStream(contentStream, true)); } catch (Exception e) { throw new UploadFailedException(e, remoteDocument); } } }
/// <summary> /// Uploads the file. /// Resumes an upload if the given localFileStream.Position is larger than zero. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException"> /// Contains the last successful remote document state. This is needed for continue a failed upload. /// </exception> public override IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { IDocument result = remoteDocument; for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) { bool isFirstChunk = offset == 0; bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length; using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize)) using (var offsetstream = new OffsetStream(chunkstream, offset)) using (var transmissionStream = transmission.CreateStream(offsetstream)) { transmission.Length = localFileStream.Length; transmission.Position = offset; chunkstream.ChunkPosition = offset; ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name); if (isLastChunk) { contentStream.Length = localFileStream.Length - offset; } else { contentStream.Length = this.ChunkSize; } contentStream.Stream = transmissionStream; try { if (isFirstChunk && result.ContentStreamId != null && overwrite) { result.DeleteContentStream(true); } result.AppendContentStream(contentStream, isLastChunk, true); HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) { hash.TransformFinalBlock(new byte[0], 0, 0); update(hash.Hash, result.ContentStreamLength.GetValueOrDefault()); } } } catch (Exception e) { if (e is FileTransmission.AbortException) { throw; } if (e.InnerException is FileTransmission.AbortException) { throw e.InnerException; } throw new UploadFailedException(e, result); } } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return(result); }
public void ConstructorTakesTransmissionAndStream() { var transmission = new Transmission(TransmissionType.DOWNLOAD_MODIFIED_FILE, "path"); using (var stream = new MemoryStream()) using (var underTest = new TransmissionStream(stream, transmission)) { } }
private void UpdateSizeAndPositionStatus(Transmission t) { string pos = t.Position != null && t.Position != t.Length ? CmisSync.Lib.Utils.FormatSize(t.Position.GetValueOrDefault()) + "/" : string.Empty; string size = t.Length != null ? CmisSync.Lib.Utils.FormatSize(t.Length.GetValueOrDefault()) : string.Empty; this.statusDetailsLabel.Markup = string.Format("<small>{0}{1}</small>", pos, size); }
private void Controller_DeleteTransmissionEvent(Transmission item) { Dispatcher.BeginInvoke((Action)delegate { this.TransmissionList.Remove(item); }); }
private void HandleInsertTransmissionEvent(Transmission item) { lock (lockTransmissionItems) { TransmissionItems.Insert(0, item); changeAll = true; } }
public void UpdateTableView(NSTableView tableView, Transmission item) { if (changeAll) { changeAll = false; BeginInvokeOnMainThread(delegate { tableView.ReloadData(); }); return; } if (item == null) { return; } // lock (lockTransmissionItems) { // for (int i = 0; i < TransmissionItems.Count; ++i) { // if (TransmissionItems[i].Path == item.Path) { // BeginInvokeOnMainThread(delegate { // tableView.ReloadData(new NSIndexSet(i), new NSIndexSet(0)); // }); // return; // } // } // } }
/// <summary> /// Uploads the file content to the remote document. /// </summary> /// <returns>The SHA-1 hash of the uploaded file content.</returns> /// <param name="localFile">Local file.</param> /// <param name="doc">Remote document.</param> /// <param name="transmissionManager">Transmission manager.</param> /// <param name="transmissionEvent">File Transmission event.</param> /// <param name="mappedObject">Mapped object saved in <c>Storage</c></param> protected byte[] UploadFileWithPWC(IFileInfo localFile, ref IDocument doc, Transmission transmission, IMappedObject mappedObject = null) { byte[] checksum = null; var docPWC = this.LoadRemotePWCDocument(doc, ref checksum); using (var file = localFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) { if (checksum != null) { // check PWC checksum for integration using (var hashAlg = new SHA1Managed()) { int bufsize = 8 * 1024; byte[] buffer = new byte[bufsize]; for (long offset = 0; offset < docPWC.ContentStreamLength.GetValueOrDefault();) { int readsize = bufsize; if (readsize + offset > docPWC.ContentStreamLength.GetValueOrDefault()) { readsize = (int)(docPWC.ContentStreamLength.GetValueOrDefault() - offset); } readsize = file.Read(buffer, 0, readsize); hashAlg.TransformBlock(buffer, 0, readsize, buffer, 0); offset += readsize; if (readsize == 0) { break; } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); if (!hashAlg.Hash.SequenceEqual(checksum)) { docPWC.DeleteContentStream(); } file.Seek(0, SeekOrigin.Begin); } } byte[] hash = null; var uploader = FileTransmission.ContentTaskUtils.CreateUploader(this.TransmissionStorage.ChunkSize); using (var hashAlg = new SHA1Reuse()) { try { using (var hashstream = new NonClosingHashStream(file, hashAlg, CryptoStreamMode.Read)) { int bufsize = 8 * 1024; byte[] buffer = new byte[bufsize]; for (long offset = 0; offset < docPWC.ContentStreamLength.GetValueOrDefault();) { int readsize = bufsize; if (readsize + offset > docPWC.ContentStreamLength.GetValueOrDefault()) { readsize = (int)(docPWC.ContentStreamLength.GetValueOrDefault() - offset); } readsize = hashstream.Read(buffer, 0, readsize); offset += readsize; if (readsize == 0) { break; } } } var document = doc; uploader.UploadFile(docPWC, file, transmission, hashAlg, false, (byte[] checksumUpdate, long length) => this.SaveRemotePWCDocument(localFile, document, docPWC, checksumUpdate, transmission)); hash = hashAlg.Hash; } catch (Exception ex) { transmission.FailedException = ex; throw; } } this.TransmissionStorage.RemoveObjectByRemoteObjectId(doc.Id); var properties = new Dictionary<string, object>(); properties.Add(PropertyIds.LastModificationDate, localFile.LastWriteTimeUtc); doc = this.Session.GetObject(docPWC.CheckIn(true, properties, null, string.Empty)) as IDocument; // Refresh is required, or DotCMIS will use cached one only doc.Refresh(); transmission.Status = TransmissionStatus.FINISHED; return hash; } }
private void UpdateViewProgress(TransmissionWidgetItem widget, Transmission t) { if (widget != null) { widget.progress.Hidden = t.Percent.GetValueOrDefault() == 100; widget.progress.DoubleValue = t.Percent.GetValueOrDefault(); if (widget.progress.Hidden) { System.Drawing.SizeF size = widget.Frame.Size; size.Height = widget.labelName.Frame.Height + widget.labelStatus.Frame.Height; widget.SetFrameSize(size); } else { System.Drawing.SizeF size = widget.Frame.Size; size.Height = widget.labelName.Frame.Height + widget.progress.Frame.Height + widget.labelStatus.Frame.Height; widget.SetFrameSize(size); } } }
private void UpdateWidgetStatus(TransmissionWidgetItem widget, Transmission t) { if (widget != null) { string pos = t.Position != null && t.Position != t.Length ? string.Format("{0}/", CmisSync.Lib.Utils.FormatSize(t.Position.GetValueOrDefault())) : string.Empty; string size = t.Length != null ? CmisSync.Lib.Utils.FormatSize(t.Length.GetValueOrDefault()) : string.Empty; string speed = !t.Done ? CmisSync.Lib.Utils.FormatBandwidth(t.BitsPerSecond.GetValueOrDefault()): string.Empty; widget.labelStatus.StringValue = string.Format("{0}{1}\t{2}", pos, size, speed); } }
private int DownloadNextChunk(IDocument remoteDocument, long offset, long remainingBytes, Transmission transmission, Stream outputstream, HashAlgorithm hashAlg) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } IContentStream contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; using (var remoteStream = contentStream.Stream) using (var forwardstream = new ForwardReadingStream(remoteStream)) using (var offsetstream = new OffsetStream(forwardstream, offset)) using (var progress = transmission.CreateStream(offsetstream)) { byte[] buffer = new byte[8 * 1024]; int result = 0; int len; while ((len = progress.Read(buffer, 0, buffer.Length)) > 0) { outputstream.Write(buffer, 0, len); hashAlg.TransformBlock(buffer, 0, len, buffer, 0); result += len; outputstream.Flush(); } return(result); } } }
private int DownloadNextChunk(IDocument remoteDocument, long offset, long remainingBytes, Transmission transmission, Stream outputstream, HashAlgorithm hashAlg) { lock(this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } IContentStream contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; using (var remoteStream = contentStream.Stream) using (var forwardstream = new ForwardReadingStream(remoteStream)) using (var offsetstream = new OffsetStream(forwardstream, offset)) using (var progress = transmission.CreateStream(offsetstream)) { byte[] buffer = new byte[8 * 1024]; int result = 0; int len; while ((len = progress.Read(buffer, 0, buffer.Length)) > 0) { outputstream.Write(buffer, 0, len); hashAlg.TransformBlock(buffer, 0, len, buffer, 0); result += len; outputstream.Flush(); } return result; } } }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { byte[] buffer = new byte[8 * 1024]; int len; if (localFileStream.Length > 0) { localFileStream.Seek(0, SeekOrigin.Begin); while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long offset = localFileStream.Position; long?fileLength = remoteDocument.ContentStreamLength; if (fileLength <= offset) { transmission.Length = fileLength.GetValueOrDefault(); transmission.Position = offset; hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } DotCMIS.Data.IContentStream contentStream = null; if (offset > 0) { long remainingBytes = (long)fileLength - offset; transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); } else { contentStream = remoteDocument.GetContentStream(); } using (var transmissionStream = transmission.CreateStream(localFileStream)) using (CryptoStream hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream != null ? contentStream.Stream : new MemoryStream(0)) { transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; int written = 0; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } try { hashstream.Write(buffer, 0, len); hashstream.Flush(); written += len; } catch (Exception) { this.UpdateHash(hashAlg, localFileStream.Length, update); throw; } if (written >= 1024 * 1024) { this.UpdateHash(hashAlg, localFileStream.Length, update); written = 0; } } } if (written > 0) { this.UpdateHash(hashAlg, localFileStream.Length, update); } } }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { byte[] buffer = new byte[8 * 1024]; int len; if (localFileStream.Length > 0) { localFileStream.Seek(0, SeekOrigin.Begin); while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long offset = localFileStream.Position; long? fileLength = remoteDocument.ContentStreamLength; if (fileLength <= offset) { transmission.Length = fileLength.GetValueOrDefault(); transmission.Position = offset; hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } DotCMIS.Data.IContentStream contentStream = null; if (offset > 0) { long remainingBytes = (long)fileLength - offset; transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); } else { contentStream = remoteDocument.GetContentStream(); } using (var transmissionStream = transmission.CreateStream(localFileStream)) using (CryptoStream hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream != null ? contentStream.Stream : new MemoryStream(0)) { transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; int written = 0; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } try { hashstream.Write(buffer, 0, len); hashstream.Flush(); written += len; } catch (Exception) { this.UpdateHash(hashAlg, localFileStream.Length, update); throw; } if (written >= 1024 * 1024) { this.UpdateHash(hashAlg, localFileStream.Length, update); written = 0; } } } if (written > 0) { this.UpdateHash(hashAlg, localFileStream.Length, update); } } }
private void SaveRemotePWCDocument(IFileInfo localFile, IDocument remoteDocument, IDocument remotePWCDocument, byte[] checksum, Transmission transmissionEvent) { if (remotePWCDocument == null) { return; } var obj = new FileTransmissionObject(transmissionEvent.Type, localFile, remoteDocument) { ChecksumAlgorithmName = "SHA-1", RemoteObjectPWCId = remotePWCDocument.Id, LastChangeTokenPWC = remotePWCDocument.ChangeToken, LastChecksumPWC = checksum }; this.TransmissionStorage.SaveObject(obj); }
private void Controller_UpdateTransmissionEvent(Transmission item) { Dispatcher.BeginInvoke((Action)delegate { if (TransmissionList.Contains(item)) { ListView_SelectionChanged(this, null); } }); }
private void Controller_InsertTransmissionEvent(Transmission item) { Dispatcher.BeginInvoke((Action)delegate { TransmissionList.Insert(0, item); }); }