Beispiel #1
0
 /// <summary>
 ///		After advancing current position to next item in online queue
 ///		check the offline queue and open top reader if it contains
 ///		items with timestamp lower or equal to the <see cref="TopReader"/>
 ///		or just open the first file in the queue if the online queue
 ///		is empty
 /// </summary>
 /// <remarks>
 ///		Call it after returning item from top online reader or after
 ///		initial seek populating the offline queue.
 /// </remarks>
 private void SyncOfflineQueueForReading()
 {
     // need to repeat because FirstTimestampInOfflineQueue is not necessarily what we will get after loading the file
     // because it's potential; the actual item timestamp may be further from the seek time but we only find it out
     // after loading the file
     while (_offlineQueue.Count > 0 &&
            (
                TopReader == null ||                                                                                             // whatever is in the offline queue is is better than nothing
                TimestampComparer.Compare(CurrentItemTimestamp, this.FirstTimestampInOfflineQueue) >= 0                          // offline is potentially prior to top reader
            ))
     {
         DateTime firstOfflineTimestamp = this.FirstTimestampInOfflineQueue;
         // if DataItemComparer is set we need to load all readers with the top timestamp
         // to enforce order
         do
         {
             RepositoryFolderReader readerToGoOnline = _offlineQueue.First.Value;
             if (readerToGoOnline.LoadNextFile())
             {
                 _onlineQueue.AddFirst(readerToGoOnline);
                 // may need to update position when timestamps are equal and the DataItemComparer is set
                 UpdateTopReaderPosition();
             }
             else
             {
                 AddToExhaustedImpl(readerToGoOnline);
             }
             _offlineQueue.RemoveFirst();
         }while (this.FirstTimestampInOfflineQueue == firstOfflineTimestamp && this.DataItemComparer != null);
     }
 }
Beispiel #2
0
        /// <summary>
        ///		<see cref="IRepositoryReader.RemoveFolder"/>
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        ///		The reader has been disposed.
        /// </exception>
        public void RemoveFolder(IRepositoryFolder folder)
        {
            CheckNotDisposed();
            Util.Check.DoRequireArgumentNotNull(folder, "folder");
            Exceptions.DifferentRepositoriesExceptionHelper.Check(folder.Repository, Repository);
            RepositoryFolderReader reader = GetExistingReader(folder.FolderKey);

            Util.Check.DoRequire(reader != null, "The folder is not being read by the reader");

            _position.Remove(reader.Position);

            reader.Unload();

            bool topReaderRemoved = this.HasData && TopReader == reader;

            bool success = !(!_exhaustedReaders.Remove(reader) && !_offlineQueue.Remove(reader) && !_onlineQueue.Remove(reader));

            Util.Check.Ensure(success, "Internal error: reader not found.");

            success = _readers.Remove(folder.FolderKey);
            Util.Check.Ensure(success);

            if (topReaderRemoved)
            {
                SyncOfflineQueueForReading();
            }

            Invariant();
        }
Beispiel #3
0
        /// <summary>
        ///		Add folder to read and optionally prepare it for reading
        /// </summary>
        /// <param name="folder">
        ///		Folder to add
        /// </param>
        /// <param name="position">
        ///		<see langword="null"/> means do not prepare it for reading
        /// </param>
        /// <returns>
        ///		<see langword="false"/> - the folder is already being read
        ///		<see langword="true"/> otherwise
        /// </returns>
        /// <remarks>
        ///		If reader has data (<see cref="HasData"/>) <paramref name="position"/> must have value
        /// </remarks>
        private bool AddFolderImpl(IRepositoryFolder folder, IFolderReadingPosition position)
        {
            Check.RequireArgumentNotNull(folder, "folder");

            IFolder folderTyped = RepositoryFolder.CastFolder(folder);

            Check.Require(object.ReferenceEquals(folder.Repository, Repository));
            Check.Require(!HasData || position != null, "If we have data we cannot leave a reader unpositioned");

            if (IsAccessing(folder, false))
            {
                return(false);
            }

            Check.Require(!_position.FolderPositions.ContainsKey(folder.FolderKey)
                          , "Folder position found in repository reader position for a folder not being read");

            RepositoryFolderReader reader = new RepositoryFolderReader(folderTyped, this);

            reader.Direction = this.Direction;

            _readers.Add(folder.FolderKey, reader);

            if (position != null)
            {
                SeekFolderReader(reader, position);
            }

            return(true);
        }
Beispiel #4
0
 /// <summary>
 ///		Add a positioned offline reader to an appropriate queue
 /// </summary>
 /// <param name="reader">
 ///		The reader must be added to all readers collection as necessary; not added here
 /// </param>
 /// <remarks>
 ///		The reader will go into either offline queue or exhausted readers collection
 /// </remarks>
 private void AddPositionedOfflineReaderToAQueue(RepositoryFolderReader reader)
 {
     if (reader.NextFileFound)
     {
         AddReaderToOfflineQueue(reader);
     }
     else
     {
         AddToExhaustedImpl(reader);
     }
 }
Beispiel #5
0
        /// <summary>
        ///		Initiate reading from the <paramref name="reader"/>.
        ///		It must not be in any of the 2 queues (online, offline) or exhausted list.
        ///		If the file contains data since <paramref name="seekTime"/> the reader will
        ///		be placed into offline queue. Otherwise it will go into exhausted readers list.
        /// </summary>
        /// <param name="reader">
        ///		Reader to initiate. It must not be in any of the 2 queues (online, offline) or exhausted list.
        /// </param>
        /// <param name="position">
        ///		Position to start reading from.
        /// </param>
        /// <remarks>
        ///		The method ensures that currently loaded reader's data is unloaded first.
        ///		Seeking is done lazily - all go to offline queue and loaded immediately
        ///		before reading.
        /// </remarks>
        private void SeekFolderReader(RepositoryFolderReader reader, IFolderReadingPosition position)
        {
            Check.RequireArgumentNotNull(position, "position");
            Check.RequireArgumentNotNull(reader, "reader");
            Check.Require(!_offlineQueue.Contains(reader) && !_exhaustedReaders.Contains(reader) && !_onlineQueue.Contains(reader));

            reader.Unload();
            reader.SeekDataFile(position);
            AddPositionedOfflineReaderToAQueue(reader);

            // as reader.Position is singleton, changes to the reader's position do not require modifying _position
            _position.SetFolderPosition(reader.Position);
        }
Beispiel #6
0
        /// <summary>
        ///		Add the specified reader to the offline queue
        /// </summary>
        /// <param name="reader">
        ///		The reader to add. Its <see cref="RepositoryFolderReader.NextFileFound"/>
        ///		must equal <see langword="true"/>.
        /// </param>
        private void AddReaderToOfflineQueue(RepositoryFolderReader reader)
        {
            Util.Check.Require(reader.NextFileFound, "Internal error: reader unsuitable for offline queue");

            // free memory
            reader.Unload();

            LinkedListNode <RepositoryFolderReader> predecessor = null;

            if (_offlineQueue.Count > 0)
            {
                predecessor = FindPredecessorInQueue(_offlineQueue.First, reader, _offlineReaderComparer);
            }
            if (null == predecessor)
            {
                _offlineQueue.AddFirst(reader);
            }
            else
            {
                _offlineQueue.AddAfter(predecessor, reader);
            }
        }
Beispiel #7
0
        /// <summary>
        ///		Find predecessor for the <paramref name="reader"/> in the queue
        ///		of readers sorted by <paramref name="readerComparer"/> ascending starting
        ///		from <paramref name="queueStart"/>
        /// </summary>
        /// <param name="queueStart">
        ///		The first element in the queue to start lookup from; all readers
        ///		in the queue must have current item
        /// </param>
        /// <param name="reader">
        ///		The reader to find place for in the queue
        /// </param>
        /// <returns>
        ///		<see langword="null"/> if the <paramref name="queueStart"/> is
        ///		positioned to a greater item than <paramref name="reader"/>
        ///		i.e. <paramref name="reader"/> must be before <paramref name="queueStart"/>
        ///		otherwise the first element in the queue which is less than the
        ///		<paramref name="reader"/>
        /// </returns>
        private LinkedListNode <RepositoryFolderReader> FindPredecessorInQueue(
            LinkedListNode <RepositoryFolderReader> queueStart
            , RepositoryFolderReader reader
            , IComparer <RepositoryFolderReader> readerComparer)
        {
            LinkedListNode <RepositoryFolderReader> retval;

            if (readerComparer.Compare(queueStart.Value, reader) >= 0)
            {
                // the reader must be before the first item in the queue
                return(null);
            }

            for (
                retval = queueStart
                ; retval.Next != null && readerComparer.Compare(retval.Next.Value, reader) < 0
                ; retval = retval.Next)
            {
                Util.Check.Ensure(readerComparer.Compare(retval.Value, reader) < 0
                                  , "Internal logic error; queue may not be sorted properly");
            }
            return(retval);
        }
Beispiel #8
0
 private void AddToExhaustedImpl(RepositoryFolderReader reader)
 {
     reader.Unload();
     _exhaustedReaders.AddLast(reader);
 }