Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
 private void WriteQueue_OnFlushSucceeded(object sender, FlushSucceededEventArgs args)
 {
     _ByteCache.Flushed(args.PhysicalPostion);
 }