/// <summary> /// This is the WriteQueueThread, here all writing takes place... /// </summary> public void WriteQueueThread() { #region Data QueueEntry actualQueueElement; Int32 Divisor, Major, Minor; #endregion #region Sleep until FileStream was attached or thread was ended while (GraphFSFileStream == null && !ShutdownWriterThread) { try { // Send this thread into sleep, it may reawake every 10ms Thread.Sleep(10); } catch (ThreadInterruptedException) { // Debug.WriteLine("[WriteQueueThread] Thread reawaken from start-up sleep (" + e + ")!"); } } #endregion // Break this loop only if Shutdown==true and WriteQueue==empty while (!(ShutdownWriterThread && WriteQueueThreadSleeping) || WriteQueue.Count > 0) { #region Pause the queue processing! if (PauseTheQueue) { Debug.WriteLine("[WriteQueueThread] Thread paused!"); lock (WriteQueueThreadEndOfPause) { // Wartet auf Unpause() Monitor.Wait(WriteQueueThreadEndOfPause); } Debug.WriteLine("[WriteQueueThread] Thread (re-)awaken from pause!"); } #endregion #region Sleep if there is nothing to do... or get next QueueEntry! actualQueueElement = null; WriteQueueThreadSleeping = false; lock (WriteQueue) { if (QueueFull && WriteQueue.Count < _MaxNumberOfQueueEntries) { lock (WriteQueueHasFreeSpace) { // Signalisiert, dass wieder Platz im Puffer ist Monitor.PulseAll(WriteQueueHasFreeSpace); } } // Falls keine Elemente zum Verbrauchen if (WriteQueue.Count == 0) { WriteQueueThreadSleeping = true; } // else get first element of the WriteQueue! else { actualQueueElement = WriteQueue[0]; WriteQueue.RemoveAt(0); } } #endregion #region Goto Sleep! if (WriteQueueThreadSleeping) { // Make sure everything is written to disc... //PhysicalFlush(); // Debug.WriteLine("[WriteQueueThread] Thread went to sleep!"); lock (WriteQueueHasNewElements) { // Wartet bis wieder ein Element vorhanden ist... aber maximal 10ms Monitor.Wait(WriteQueueHasNewElements, 10); } // Debug.WriteLine("[WriteQueueThread] Thread (re-)awake from sleep!"); } #endregion #region Write QueueEntry if (actualQueueElement != null) { // Debug.WriteLine("[WriteQueueThread] Number of entries: " + WriteQueue.Count); lock (GraphFSFileStream) { #region Write Extents foreach (var _ObjectExtent in actualQueueElement.RWQueueStreams) { // The actual .NET framework can only write 2^32 bytes at once! // So check if the extent logical position plus its length is // smaller than the getLatestRevisionTime value of a 32 bit integer: // If yes, write at once.. if (_ObjectExtent.LogicalPosition + _ObjectExtent.Length <= Int32.MaxValue) { GraphFSFileStream.Seek((Int64)_ObjectExtent.PhysicalPosition, 0); GraphFSFileStream.Write(actualQueueElement.Data, (Int32)_ObjectExtent.LogicalPosition, (Int32)Math.Min(_ObjectExtent.Length, (UInt64)actualQueueElement.Data.Length - _ObjectExtent.LogicalPosition)); _BytesWritten += _ObjectExtent.Length; // Debug.WriteLine("[WriteQueue] Writing " + myExtent.Length + " bytes at position " + myExtent.PhysicalPosition); } // If no, write in smaller pieces! else { Divisor = Int32.MaxValue / 8; Major = (Int32)_ObjectExtent.Length / Divisor; Minor = (Int32)_ObjectExtent.Length % Divisor; var tmpData = new Byte[Divisor]; for (Int32 i = 0; i < Major; i++) { actualQueueElement.Data.CopyTo(tmpData, i * Divisor); GraphFSFileStream.Seek((Int64)_ObjectExtent.PhysicalPosition + i * Divisor, 0); GraphFSFileStream.Write(tmpData, 0, Divisor); _BytesWritten += (UInt64)Divisor; } // Write the rest of the data actualQueueElement.Data.CopyTo(tmpData, Major * Divisor); GraphFSFileStream.Seek((Int64)_ObjectExtent.PhysicalPosition + Major * Divisor, 0); GraphFSFileStream.Write(tmpData, 0, Minor); _BytesWritten += (UInt64)Minor; } // CORRECTION: Remove this Entry from Writequeue - Prevent Readqueue from reading not yet written positions //_WriteQueueLock.RemoveLock(_ObjectExtent.PhysicalPosition); if (OnFlushSucceeded != null) { var args = new FlushSucceededEventArgs(_ObjectExtent.PhysicalPosition, _BytesWritten); OnFlushSucceeded(this, args); } } #endregion } // Check if the FileStream has to be flushed now if (actualQueueElement.FlushAfterWrite) PhysicalFlush(); } #endregion } ShutdownWriterThread = false; QueueIsOffline = true; PhysicalFlush(); //Debug.WriteLine("WriteQueue.Count: " + WriteQueue.Count); //Debug.WriteLine(" \t_WriteQueuePositions" + ((List<UInt64>)UnitTestHelper.GetPrivateField("_WriteQueuePositions", _WriteQueueLock)).Count); }
private void WriteQueue_OnFlushSucceeded(object sender, FlushSucceededEventArgs args) { _ByteCache.Flushed(args.PhysicalPostion); }