public async Task Can_Recover_From_Missing_Data() { var connection = GetConnection(); var repository = GetRepository(); SessionHeader header; var fileLength = 0L; using (var sessionStream = File.OpenRead(Path.Combine(TestContext.CurrentContext.TestDirectory, "Content", "SampleSession.glf"))) { sessionStream.Position = 0; var reader = new GLFReader(sessionStream); header = reader.SessionHeader; fileLength = sessionStream.Length; repository.AddSession(sessionStream); } using (var request = new SessionUploadRequest(repository.Id, repository, header.Id, header.FileId, false)) { var progressFile = request.GenerateTemporarySessionFileNamePath(); //mess with the progress file... using (var sessionTrackingFileStream = new FileStream(progressFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { using (var writer = new BinaryWriter(sessionTrackingFileStream, Encoding.UTF8)) { var partialFileLength = Convert.ToInt64(fileLength * 0.7); writer.Write(partialFileLength); writer.Flush(); sessionTrackingFileStream.SetLength(sessionTrackingFileStream.Position); } } //because upload request uses a multiprocess lock we put it in a using to ensure it gets disposed. //explicitly prepare the session - this returns true if we got the lock meaning no one else is actively transferring this session right now. Assert.IsTrue(request.PrepareSession()); //this should internally recover from starting mid-stream. await connection.ExecuteRequest(request, 0).ConfigureAwait(false); } }
/// <summary> /// Sends a merged session stream or a single session fragment file to the server. /// </summary> /// <param name="sessionId"></param> /// <param name="fileId"></param> /// <param name="maxRetries">The maximum number of times to retry the session data upload.</param> /// <param name="purgeSentSessions">Indicates whether to purge sessions that have been successfully sent from the repository</param> /// <returns>Throws an exception if the upload fails.</returns> private async Task PerformSessionFileUpload(Guid sessionId, Guid?fileId, int maxRetries, bool purgeSentSessions) { using (var request = new SessionUploadRequest(m_SourceRepository.Id, m_SourceRepository, sessionId, fileId, purgeSentSessions)) { //because upload request uses a multiprocess lock we put it in a using to ensure it gets disposed. //explicitly prepare the session - this returns true if we got the lock meaning no one else is actively transferring this session right now. if (request.PrepareSession() == false) { if (!Log.SilentMode) { Log.Write(LogMessageSeverity.Information, LogCategory, "Skipping sending session to server because another process already is transferring it", "We weren't able to get a transport lock on the session '{0}' so we assume another process is currently sending it.", sessionId); } } else { await m_HubConnection.ExecuteRequest(request, maxRetries).ConfigureAwait(false); } } }