/// <summary> /// The Writequeue add a new Position to the Lock /// </summary> /// <param name="Position">The Physical Position on the storage</param> public void Add(QueueEntry QueueEntry) { // this will work only if we have just 1 Stream and 1 Extent!!! foreach (var ObjectExtent in QueueEntry.RWQueueStreams) { var WriteQueuePositions = new Dictionary<UInt64, Byte[]>(); lock (_Storages) { if (_Storages[ObjectExtent.StorageUUID] == null) _Storages.Add(ObjectExtent.StorageUUID, WriteQueuePositions); else WriteQueuePositions = (Dictionary<UInt64, Byte[]>)_Storages[ObjectExtent.StorageUUID]; try { if (WriteQueuePositions.ContainsKey(ObjectExtent.PhysicalPosition)) { // System.Diagnostics.Debug.WriteLine("[WriteCache]" + ObjectExtent.StorageID + "(" + WriteQueuePositions.Count + ") Overwrite " + ObjectExtent.PhysicalPosition + " Data: " + QueueEntry.Data.Length); WriteQueuePositions[ObjectExtent.PhysicalPosition] = QueueEntry.Data; } else { // System.Diagnostics.Debug.WriteLine("[WriteCache]" + ObjectExtent.StorageID + "(" + WriteQueuePositions.Count + ") Add " + ObjectExtent.PhysicalPosition + " Data: " + QueueEntry.Data.Length); WriteQueuePositions.Add(ObjectExtent.PhysicalPosition, QueueEntry.Data); } } catch { } } } }
/// <summary> /// Adds a Write request to the WriteQueue; if more than _MaxNumberOfQueueEntries are in the Queue /// we wait until there's less. /// </summary> /// <param name="newEntry">the WriteQueueEntry</param> public void Write(QueueEntry newEntry) { Boolean WriteSucceeded = false; Int16 WriteAttempt = 0; // Wait, while the queue is flushing its entries while (BlockQueueInsertion) Thread.Sleep(1); if (ShutdownWriterThread) throw new QueueManagerException("[WriteQueue] Write failed, because the WriteQueueThread was shut down!"); if (QueueIsOffline) throw new QueueManagerException("[WriteQueue] Write failed, because the WriteQueueThread is offline!"); while (!WriteSucceeded && WriteAttempt <= _MaxNumberOfWriteAttempts) { QueueFull = false; // Lock until WriteQueue get's free to use... lock (WriteQueue) { if (WriteQueue.Count >= _MaxNumberOfQueueEntries) // Falls Puffer voll { QueueFull = true; //NStorageEngine_WriteQueueFull.Arguments args = new NStorageEngine_WriteQueueFull.Arguments(); //args.NumberOfQueueEntries = NumberOfQueueEntries; //NotificationDispatcher.SendNotification(typeof(NStorageEngine_WriteQueueFull), args); } } if (QueueFull) lock (WriteQueueHasFreeSpace) { // Wartet bis wieder Platz im Puffer vorhanden ist Monitor.Wait(WriteQueueHasFreeSpace); QueueFull = false; } lock (WriteQueue) { WriteAttempt++; if (WriteQueue.Count < _MaxNumberOfQueueEntries) { WriteQueue.Add(newEntry); // CORRECTION: Add a new Entry to Writequeue - Prevent Readqueue from reading not yet written positions /* foreach (var _ObjectExtent in newEntry.RWQueueStreams) _WriteQueueLock.AddLock(_ObjectExtent.PhysicalPosition); */ // Debug.WriteLine("[WriteQueue] Adding new entry!"); //Debug.WriteLine("[WriteQueueThread] Added to the queue!"); // Wake the WriteQueueThread if it was fallen asleep WriteSucceeded = true; if (WriteQueueThreadSleeping) lock (WriteQueueHasNewElements) { // Signalisiert, dass wieder ein Element vorhanden ist Monitor.PulseAll(WriteQueueHasNewElements); } } } } // ...fail afterwards! // This should actually never happen!!! if (!WriteSucceeded) throw new QueueManagerCouldNotWriteQueueException("[WriteQueue] Could not write to the queue!"); }
/// <summary> /// Reads a pile of data from the filesystem /// </summary> /// <param name="ReadEntry">a QueueEntry </param> /// <returns></returns> public byte[] Read(QueueEntry ReadEntry) { // check size if (ReadEntry.DataLength > Int32.MaxValue) throw new QueueManagerException("Cannot read QueueEntry - it's too big."); byte[] Output = new byte[ReadEntry.DataLength]; // TODO: actually make use of the read queue... if (!GraphFSFileStream.CanRead) throw new QueueManagerException("Cannot read. Maybe nothing is mounted."); // CORRECTION: Check if the current StartPosition is still in the WriteQueue - Prevent Readqueue from reading not yet written positions /* while (_WriteQueueLock.HasLock(ReadEntry.RWQueueStreams[0].PhysicalPosition)) { Debug.WriteLine("[ReadQueue] has lock at Position " + ReadEntry.RWQueueStreams[0].PhysicalPosition); Thread.Sleep(1); // or read next in queue } */ lock (GraphFSFileStream) { GraphFSFileStream.Seek( (long) ReadEntry.RWQueueStreams[0].PhysicalPosition, 0); Int32 HowMany = GraphFSFileStream.Read(Output, 0, (Int32)ReadEntry.RWQueueStreams[0].Length); if (_BytesRead + (UInt64) HowMany < 0) _BytesRead = 0; _BytesRead += (UInt64) HowMany; } //Debug.WriteLine("[ReadQueue] Reading " + Output.Length + " bytes from position " + ReadEntry.Streams[0].Extents[0].PhysicalPosition); //Debug.WriteLine(" \t_WriteQueuePositions" + ((List<UInt64>)UnitTestHelper.GetPrivateField("_WriteQueuePositions", _WriteQueueLock)).Count); return Output; }
/// <summary> /// This method writes directly a QueueEntry as soon as possible on disc. /// It does this by putting the QueueEntry infront of all other QueueEntries /// within the queue. /// In most cases this is not what you want: USE WITH CARE! /// </summary> /// <param name="newEntry">the QueueEntry that needs to be written as soon as possible</param> public void DirectWrite(QueueEntry newEntry) { // Wait, while the queue is flushing its entries while (BlockQueueInsertion) Thread.Sleep(1); if (ShutdownWriterThread) throw new QueueManagerException("[WriteQueue] Write failed, because the WriteQueueThread was shut down!"); if (QueueIsOffline) throw new QueueManagerException("[WriteQueue] Write failed, because the WriteQueueThread is offline!"); newEntry.FlushAfterWrite = true; lock (WriteQueue) { WriteQueue.Insert(0, newEntry); } }