/// <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);
        }
Example #2
0
        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 &amp; 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);
            }
        }
Example #5
0
        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();
        }
Example #6
0
        /// <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);
                }
            }
        }