/// <inheritdoc /> public List <StoredFrame> ReadBetween( DateTime inclusiveFrom, DateTime exclusiveTo ) { var frames = ReadFramesFromDb(inclusiveFrom, exclusiveTo); var frameGroups = ( from frame in frames group frame by frame.FilePath into frameGroup select frameGroup ).ToList(); foreach (var frameGroup in frameGroups) { lock (TargetFileLocker.GetFileLocker(frameGroup.Key)) { using (var fs = File.OpenRead(frameGroup.Key)) { foreach (var frame in frameGroup.OrderBy(f => f.Offset)) { fs.Position = frame.Offset; var compressedBody = new byte[frame.Length]; fs.Read(compressedBody, 0, compressedBody.Length); using (var targetStream = new MemoryStream(compressedBody)) { using (var decompressionStream = new GZipStream(targetStream, CompressionMode.Decompress)) { using (var sr = new StreamReader(decompressionStream, Encoding.UTF8)) { var body = sr.ReadToEnd(); frame.AppendBody(body); } } } } } } } return(frames); }
/// <inheritdoc /> protected override void LogCompleteMessage( string message ) { //zip message... byte[] zippedMessage; using (var targetStream = new MemoryStream()) { using (var compressionStream = new GZipStream(targetStream, CompressionMode.Compress)) { using (var sw = new StreamWriter(compressionStream, Encoding.UTF8)) { sw.Write(message); } } zippedMessage = targetStream.ToArray(); } //determine target file... var(targetFilePath, targetFolderPath, targetFileName) = _targetController.GetTargetFile(); //append data var offset = 0L; lock (TargetFileLocker.GetFileLocker(targetFilePath)) { using (var fs = new FileStream(targetFilePath, FileMode.Append, FileAccess.Write)) { offset = fs.Position; fs.Write(zippedMessage, 0, zippedMessage.Length); fs.Flush(); } //we should still hold the file lock here for the case of revert //otherwise different thread (different SqlServerCollectionSaver) //can append their data between append ours and revert ours //in that case we will truncate both records and DB-metadata will be completely invalid //save metadata to DB try { _command.Parameters["fileName"].Value = targetFileName.GetFromLast(261); _command.Parameters["offset"].Value = offset; _command.Parameters["length"].Value = zippedMessage.Length; _command.ExecuteNonQuery(); } catch (Exception firstException) { //shit happens... //try to revert the file to its original state try { using (var fs = new FileStream(targetFilePath, FileMode.Open, FileAccess.ReadWrite)) { fs.SetLength(offset); } } catch (Exception secondException) { //reverting fails, this file is unrecoverable //force to switch the file! _targetController.SwitchTargetFile(); throw new AggregateException(firstException, secondException); } throw; } } //success }