Example #1
0
        /// <summary>
        /// Starts a task that is responsible for deserializing all non-path events as fed to it through the specified queue
        /// </summary>
        /// <param name="nonPathEventsToDeserialize">The queue where non-path events (as file positions) to deserialize will be fed</param>
        /// <returns>A task that will finish when the queue that it consumes from is both marked completed and empty</returns>
        private Task CreateNonPathEventConsumerTask(BlockingCollection <long> nonPathEventsToDeserialize)
        {
            return(Task.Run(() =>
            {
                using (FileStream fileStream = File.Open(m_logFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    ParallelEventReader parallelEventReader = new ParallelEventReader(this, fileStream);
                    while (!nonPathEventsToDeserialize.IsCompleted)
                    {
                        // Get next event file position
                        long positionToDeserialize;
                        try
                        {
                            positionToDeserialize = nonPathEventsToDeserialize.Take();
                        }
                        catch (InvalidOperationException)
                        {
                            // This exception is thrown when CompleteAdding is called while we are blocked on the call to Take
                            // If we see this exception, we know we are done processing events and the task can exit
                            return;
                        }

                        // Seek to the start of the next event to deserialize
                        fileStream.Seek(positionToDeserialize, SeekOrigin.Begin);

                        EventHeader header = EventHeader.ReadFrom(parallelEventReader);
                        // Ensure that event id is NOT an AddPath event
                        Contract.Assert((BinaryLogger.LogSupportEventId)header.EventId != BinaryLogger.LogSupportEventId.AddPath);

                        var startOfNextEvent = fileStream.Position + header.EventPayloadSize;

                        // Handle the internal events
                        if (header.EventId < (uint)BinaryLogger.LogSupportEventId.Max)
                        {
                            switch ((BinaryLogger.LogSupportEventId)header.EventId)
                            {
                            case BinaryLogger.LogSupportEventId.StartTime:
                                ReadStartTimeEvent(parallelEventReader);
                                break;

                            case BinaryLogger.LogSupportEventId.AddStringId:
                                ReadStringIdEvent(parallelEventReader);
                                break;
                            }

                            Contract.Assert(fileStream.Position == startOfNextEvent);
                            continue;
                        }
                        else
                        {
                            header.EventId -= (uint)BinaryLogger.LogSupportEventId.Max;
                        }

                        EventHandler handler;
                        if ((m_handlers.Length > header.EventId) &&
                            ((handler = m_handlers[header.EventId]) != null))
                        {
                            handler(header.EventId, header.WorkerId, header.Timestamp, parallelEventReader);
                            Contract.Assert(fileStream.Position <= startOfNextEvent, "Event handler read beyond the event payload");
                        }
                    }
                }
            }));
        }