/// <summary> /// Add a new session file from the provided data stream. /// </summary> /// <param name="glfReader"></param> /// <returns>The session file object for the provided data stream.</returns> internal SessionFragment Add(GLFReader glfReader) { if (glfReader == null) { throw new ArgumentNullException(nameof(glfReader)); } if (glfReader.IsSessionStream == false) { throw new ArgumentException("The provided file is not a valid session file and can't be loaded."); } SessionFragment sessionFragment; lock (m_Lock) { //make sure we don't already have this file m_SessionFilesById.TryGetValue(glfReader.SessionHeader.FileId, out sessionFragment); if (sessionFragment == null) { //we don't already have this file - add it sessionFragment = new SessionFragment(glfReader); AddItem(sessionFragment); //not our Add overload because we don't want to send the collection changed event while in our lock. } //and lets refresh our session's cached information if we are increasing values. m_Session.IntegrateHeader(glfReader.SessionHeader); } OnCollectionChanged(new CollectionChangedEventArgs <SessionFragmentCollection, SessionFragment>(this, sessionFragment, CollectionAction.Added)); return(sessionFragment); }
internal Session Add(GLFReader sessionFileReader) { if (sessionFileReader == null) { throw new ArgumentNullException(nameof(sessionFileReader)); } Session session = null; if (sessionFileReader.IsSessionStream) { lock (m_Lock) { //OK, it's a GLF. But do we already have a session this relates to? m_SessionsById.TryGetValue(sessionFileReader.SessionHeader.Id, out session); if (session == null) { //gotta make a new session session = new Session(sessionFileReader); Add(session); } else { //there is already a session - but does it have this fragment? session.Fragments.Add(sessionFileReader); } } } return(session); }
/// <summary> /// Attempt to load the session header from the specified file, returning null if it can't be loaded /// </summary> /// <param name="sessionFileNamePath">The full file name & path</param> /// <returns>The session header, or null if it can't be loaded</returns> private SessionHeader SafeGetSessionHeader(string sessionFileNamePath) { #if DEBUG if (m_LoggingEnabled) { Log.Write(LogMessageSeverity.Verbose, LogCategory, "Opening session file to read header", "Opening file {0}.", sessionFileNamePath); } #endif SessionHeader header = null; try { FileStream sourceFile = null; using (sourceFile = FileHelper.OpenFileStream(sessionFileNamePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) { if (sourceFile == null) { if (m_LoggingEnabled) { Log.Write(LogMessageSeverity.Verbose, LogCategory, "Unable to open session file, it is probably locked", "While attempting to open the local session fragment at '{0}', probably because it is still being written to.", sessionFileNamePath); } } using (var sourceGlfFile = new GLFReader(sourceFile)) { if (sourceGlfFile.IsSessionStream) { header = sourceGlfFile.SessionHeader; } } } } catch (Exception ex) { if (m_LoggingEnabled) { Log.Write(LogMessageSeverity.Warning, LogWriteMode.Queued, ex, LogCategory, "Unexpected exception while attempting to load a session header", "While opening the file '{0}' an exception was thrown reading the session header. Since this routine is designed to not generate exceptions this may indicate a flaw in the logic of the routine.\r\nException: {1}\r\n", sessionFileNamePath, ex.Message); } } return(header); }
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); } }
internal SessionFragment(GLFReader sessionFile) { if (sessionFile == null) { throw new ArgumentNullException(nameof(sessionFile)); } if (sessionFile.SessionHeader.HasFileInfo == false) { throw new ArgumentException("The session file is missing file information and can't be used as a session fragment. This indicates a coding error in the framework.", nameof(sessionFile)); } m_SessionFile = sessionFile; m_Packet = new SessionFragmentPacket(); m_Packet.ID = m_SessionFile.SessionHeader.FileId; m_Packet.FileStartDateTime = m_SessionFile.SessionHeader.FileStartDateTime; m_Packet.FileEndDateTime = m_SessionFile.SessionHeader.FileEndDateTime; m_Packet.IsLastFile = m_SessionFile.SessionHeader.IsLastFile; //and we need to make sure our session file actually has the packet stream loaded. sessionFile.EnsureDataLoaded(); }
/// <summary> /// Add a session from the provided GLF File stream /// </summary> /// <param name="fileStream">A file stream of a GLF File to read.</param> /// <param name="useOriginalStream">If true, the caller no longer owns the stream and must not further use or dispose /// it. If false, the method will copy the contents of the stream before returning and will restore its Position, /// so the caller is responsible for eventually disposing it.</param> /// <returns>The session object that was affected.</returns> public Session Add(Stream fileStream, bool useOriginalStream) { if (fileStream == null) { throw new ArgumentNullException(nameof(fileStream)); } long originalPosition = fileStream.Position; if (GLFReader.IsGLF(fileStream) == false) // This also throws an exception if the stream is not seekable. { fileStream.Position = originalPosition; throw new ArgumentException("The provided data stream is not a valid GLF session stream.", nameof(fileStream)); } Stream newStream; if (useOriginalStream == false) { // Uh-oh, the caller wants to keep the stream themselves. We need to punt a copy from the original stream. fileStream.Position = 0; // Reset its position to the start of the file to copy from the start. newStream = FileSystemTools.GetTempFileStreamCopy(fileStream); // Get a delete-on-close temp file copied from it. newStream.Position = originalPosition; // Should it do this? fileStream.Position = originalPosition; // And set it back where it had been. } else { // Otherwise, they're saying the file will stick around for us. We own it now. Or rather, the GLFReader will. newStream = fileStream; } GLFReader glfReader = new GLFReader(newStream); //now forward to our GLF Reader add which is shared with other things Session newSession = Add(glfReader); return(newSession); }
public void Export(ExportConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (string.IsNullOrWhiteSpace(configuration.SourceFileNamePath)) { throw new ArgumentNullException("SourceFileNamePath"); } //See if the local file even exists.. Console.WriteLine("Opening Source File '{0}'...", configuration.SourceFileNamePath); using (var sourceFileStream = File.OpenRead(configuration.SourceFileNamePath)) { if (GLFReader.IsGLF(sourceFileStream) == false) { throw new InvalidOperationException("Specified source file is not a Loupe Log file (glf)"); } var sessionCollection = new SessionCollection(); var session = sessionCollection.Add(sourceFileStream); if (session == null) { throw new InvalidOperationException("Unable to find session data in source data file"); } Console.WriteLine("Initializing {0} Export...", configuration.LogMessageFormat); using (session) { //instance the correct exporter... LogMessageFormatter messageFormatter; switch (configuration.LogMessageFormat) { case LogMessageFormat.Default: messageFormatter = new DefaultLogMessageFormatter(configuration); break; case LogMessageFormat.Summary: messageFormatter = new SummaryLogMessageFormatter(configuration); break; case LogMessageFormat.Detailed: messageFormatter = new DetailedLogMessageFormatter(configuration); break; default: throw new ArgumentOutOfRangeException(); } ISession readOnlySession = new ReadOnlySession(session); var stopwatch = Stopwatch.StartNew(); Console.WriteLine("Exporting Session Data into '{0}'...", configuration.TargetFileNamePath); messageFormatter.Export(readOnlySession); stopwatch.Stop(); Console.WriteLine("Completed export in {0:T}.", stopwatch.Elapsed); } } }