/// <summary> /// Closes the underlying stream and stops the flight recorder. /// </summary> /// <remarks> /// <note> /// All subsequent attempts to record events will be ignored. /// </note> /// </remarks> public void Close() { lock (syncLock) { if (!isRunning) { return; } if (IsPassThruMode) { isRunning = false; return; } Save(); if (stream != null) { stream.Close(); stream = null; } isRunning = false; GC.SuppressFinalize(this); } }
/// <summary> /// Hashes data from a stream. /// </summary> /// <param name="es">The input stream.</param> /// <param name="length">The number of bytes to hash.</param> /// <returns>The hashed digest.</returns> /// <remarks> /// The method will hash length bytes of the stream from the current position /// and the stream position will be restored before the method /// returns. /// </remarks> public static byte[] Compute(EnhancedStream es, long length) { MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); long streamPos; byte[] buf; int cb; streamPos = es.Position; buf = new byte[8192]; while (length > 0) { cb = (int)(length > buf.Length ? buf.Length : length); if (es.Read(buf, 0, cb) < cb) { throw new InvalidOperationException("Read past end of stream."); } md5.TransformBlock(buf, 0, cb, buf, 0); length -= cb; } md5.TransformFinalBlock(buf, 0, 0); es.Seek(streamPos, SeekOrigin.Begin); return(md5.Hash); }
/// <summary> /// Constructs an instance by deseralizing from a stream. /// </summary> /// <param name="input">The input stream.</param> public ArgCollection(EnhancedStream input) { this.assignChar = '='; this.sepChar = (char)0; if (input == null) { throw new ArgumentException("input"); } if (input.ReadInt16() != Magic) { throw new FormatException("ArgCollection: Invalid magic number."); } var count = input.ReadInt16(); for (int i = 0; i < count; i++) { var name = input.ReadString16(); var value = input.ReadString32(); this[name] = value; } }
/// <summary> /// Uses the HMAC/MD5 algorithm to hash data from a stream. /// </summary> /// <param name="key">The secret key.</param> /// <param name="es">The input stream.</param> /// <param name="length">The number of bytes to hash.</param> /// <returns>The hashed digest.</returns> /// <remarks> /// The method will hash length bytes of the stream from the current position. /// and the stream position will be restored before the method /// returns. /// </remarks> public static byte[] Compute(byte[] key, EnhancedStream es, int length) { byte[] hash; long pos; pos = es.Position; hash = Compute(key, es.ReadBytes(length)); es.Seek(pos, SeekOrigin.Begin); return(hash); }
/// <summary> /// Serializes the set values to a stream. /// </summary> /// <param name="output">The output stream.</param> public void Write(EnhancedStream output) { output.WriteInt16(Magic); output.WriteInt16(this.Count); foreach (var key in this) { output.WriteString16(key); output.WriteString32(this[key]); } }
/// <summary> /// Persists the event to a stream. /// </summary> /// <param name="stream">The output stream.</param> public void Write(EnhancedStream stream) { stream.WriteInt64(this.TimeUtc.Ticks); stream.WriteString16(this.OrganizationID); stream.WriteString16(this.UserID); stream.WriteString16(this.SessionID); stream.WriteString16(this.Source); stream.WriteString16(this.SourceVersion != null ? this.SourceVersion.ToString() : null); stream.WriteString16(this.Operation); stream.WriteBool(this.IsError); stream.WriteString32(this.Details); }
/// <summary> /// Constructs an instance by reading from a <see cref="Stream" />. /// </summary> /// <param name="stream">The input stream.</param> public FlightEvent(EnhancedStream stream) { this.TimeUtc = new DateTime(stream.ReadInt64()); this.OrganizationID = stream.ReadString16(); this.UserID = stream.ReadString16(); this.SessionID = stream.ReadString16();; this.Source = stream.ReadString16(); var value = stream.ReadString16(); this.SourceVersion = value == null ? null : new Version(value); this.Operation = stream.ReadString16(); this.IsError = stream.ReadBool(); this.Details = stream.ReadString32(); }
/// <summary> /// Constructs a flight recorder that runs in <b>persist</b> mode, /// saving events to the file system until the can be dequeued and /// processed by the application. /// </summary> /// <param name="path">Path to the log file.</param> /// <remarks> /// <para> /// For Silverlight builds, the <paramref name="path" /> parameter specifies /// a file within the application's isolated storage. For non-Silverlight /// builds, the parameter specifies a normal file system path and the /// constructor will attempt to create the directory tree as necessary. /// </para> /// <note> /// If the file cannot be opened for any reason (typically because another /// instance of the application has already opened the file) then a memory /// stream will be created and used instead. /// </note> /// </remarks> public FlightRecorder(string path) { try { #if SILVERLIGHT using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { this.stream = new EnhancedStream(store.OpenFile(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)); } #else Helper.CreateFileTree(path); this.stream = new EnhancedFileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite); #endif } catch (Exception e) { SysLog.LogException(e); this.stream = new EnhancedMemoryStream(); } Load(); }
/// <summary> /// Constructs a flight recorder that runs in <b>persist</b> mode, /// saving events to a <see cref="Stream" /> until the can be dequeued and /// processed by the application. /// </summary> /// <param name="stream">The log stream.</param> /// <remarks> /// <note> /// The stream must implement the following members: <see cref="Stream.Position" /> and <see cref="Stream.SetLength" /> /// such the the stream position and stream length can be changed. /// </note> /// </remarks> public FlightRecorder(Stream stream) { this.stream = new EnhancedStream(stream); Load(); }
/// <summary> /// Serializes the object graph to a stream, optionally compressing /// the output. /// </summary> /// <param name="output">The output stream.</param> /// <param name="graph">The object graph.</param> /// <param name="compress">A <see cref="Compress" /> value indicating whether compression is to be performed.</param> /// <remarks> /// <note>It is possible to serialize <c>null</c> graphs using this method.</note> /// </remarks> public static void ToBinary(Stream output, object graph, Compress compress) { // Handle null graphs if (graph == null) { int flags = Flag_IsNull; output.WriteByte((byte)(Magic >> 8)); output.WriteByte(unchecked ((byte)Magic)); output.WriteByte((byte)(flags >> 8)); output.WriteByte((byte)flags); return; } // Handle serialization of real graphs var formatter = new BinaryFormatter(); // Initalize the formatter formatter.AssemblyFormat = FormatterAssemblyStyle.Full; formatter.TypeFormat = FormatterTypeStyle.TypesAlways; if (compress == Compress.None || compress == Compress.Always) { int flags = compress == Compress.Always ? Flag_Compress : 0; // Write the header output.WriteByte((byte)(Magic >> 8)); output.WriteByte(unchecked ((byte)Magic)); output.WriteByte((byte)(flags >> 8)); output.WriteByte((byte)flags); // Serialize if (compress == Compress.Always) { using (DeflateStream ds = new DeflateStream(output, CompressionMode.Compress, true)) formatter.Serialize(ds, graph); } else { formatter.Serialize(output, graph); } } else { // We need to serialize the graph to a memory stream and then // decide whether to use the compressed or uncompressed form // based on which is smaller. using (MemoryStream msUncompressed = new MemoryStream(1024)) { Stream serialized; int flags = 0; formatter.Serialize(msUncompressed, graph); msUncompressed.Position = 0; using (MemoryStream msCompressed = new MemoryStream((int)msUncompressed.Length / 2)) { using (DeflateStream ds = new DeflateStream(msCompressed, CompressionMode.Compress, true)) { EnhancedStream.Copy(msUncompressed, ds, int.MaxValue); ds.Flush(); } if (msCompressed.Length < msUncompressed.Length) { flags |= Flag_Compress; serialized = msCompressed; } else { serialized = msUncompressed; } // Write the header output.WriteByte((byte)(Magic >> 8)); output.WriteByte(unchecked ((byte)Magic)); output.WriteByte((byte)(flags >> 8)); output.WriteByte((byte)flags); // Write the serialized data serialized.Position = 0; EnhancedStream.Copy(serialized, output, int.MaxValue); } } } }