Example #1
0
 /// <summary>
 ///     Get data file iterator.
 /// </summary>
 /// <param name="folder">
 ///     Folder whose data files to iterate over.
 /// </param>
 /// <param name="backwards">
 ///     Initial iteration direction.
 /// </param>
 /// <returns>
 ///     <see cref="IDataFileIterator"/>
 /// </returns>
 /// <remarks>
 ///		Note that you must call one of the Seek methods to start iteration after the iterator instance is created.
 /// </remarks>
 public IDataFileIterator GetDataFileIterator(IRepositoryFolder folder, bool backwards)
 {
     CheckHelper.CheckRepositoryNotDisposed(Repository);
     Check.DoRequireArgumentNotNull(folder, "folder");
     RepositoryFolder.CheckNotDetached(folder);
     return(new DataFileIterator(folder, backwards));
 }
Example #2
0
        /// <summary>
        ///		Check read and/or write access status to the <paramref name="folder"/>.
        /// </summary>
        /// <param name="folder">
        ///		Folder to check current access to.
        /// </param>
        /// <param name="subtree">
        ///		Whether to check access to all folders in the subtree or only to the <paramref name="folder"/> itself
        /// </param>
        /// <param name="read">
        ///		Whether to check read access, i.e. whether target folder[s] is/are being read from
        /// </param>
        /// <param name="write">
        ///		Whether to check write access, i.e. whether target folder[s] is/are being written to
        /// </param>
        /// <remarks>
        ///		Access to readers and writers registry is synchronised; all concurrent calls accessing registry of readers and writers
        ///		will wait until this method finishes.
        /// </remarks>
        private bool IsDataBeingAccessed(IRepositoryFolder folder, bool subtree, bool write, bool read)
        {
            Exceptions.DifferentRepositoriesExceptionHelper.Check(this, folder.Repository);
            Util.Check.Require(write || read);

            IFolder f = RepositoryFolder.CastFolder(folder, "folder");

            bool retval = false;

            _dataAccessorRegistryLock.EnterReadLock();
            try
            {
                if (read)
                {
                    retval = IsDataBeingAccessed(_readers, f, subtree);
                }
                if (!retval && write)
                {
                    retval = IsDataBeingAccessed(_writers, f, subtree);
                }
            }
            finally
            {
                _dataAccessorRegistryLock.ExitReadLock();
            }
            return(retval);
        }
        public void TestWritingNotInOrder()
        {
            const string subFolderName = "TestWritingNotInOrder";

            const int desiredFileSize = 100;

            Mock.MultiLevelDataRouter router = new Mock.MultiLevelDataRouter(2, 2);

            IRepositoryFolder targetFolder = Repository.RootFolder.GetDescendant(FixtureRootRepoFolder.LogicalPath, false).CreateSubfolder(subFolderName);

            targetFolder.Properties.DesiredItemsPerFile = desiredFileSize;


            const int itemCount       = 100000;
            const int intervalMinutes = 1;

            IDataItem[] data = GetTestData(itemCount, DateTime.Now, intervalMinutes);

            for (int j = 0; j < 2; ++j)
            {
                using (IRepositoryWriter writer = GetWriter(targetFolder, router))
                {
                    for (int n = j; n < itemCount; n = n + 2)
                    {
                        writer.Write(dataItem: data[n]);
                    }
                }
            }

            // the following commented out call is necessary if writing was done instandalone instance because target folder does not know that subfolders have been created
            // during writing; but now I am not using standalone writer
            //targetFolder.Refresh(true, true);

            CheckAllDataInFolder(targetFolder, data);
        }
Example #4
0
 public static FolderContainsSubfoldersException GetCannotDelete(IRepositoryFolder folder)
 {
     return(new FolderContainsSubfoldersException(
                folder
                , string.Format(Storage.StorageResources.CannotDeleteFolderWithSubfolders, folder.LogicalPath)
                ));
 }
Example #5
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();
        }
        public void CreateSubfolderTest()
        {
            string subFolderName = "CreateSubfolderTest";

            int initialSubfoldersCount = FixtureRootRepoFolder.SubFolders.Count;

            IRepositoryFolder subfolder1 = FixtureRootRepoFolder.CreateSubfolder(subFolderName);
            IRepositoryFolder rootFoder  = Repository.RootFolder;

            string fullPath = subfolder1.FullPath;

            Assert.IsTrue(((IFolder)subfolder1).Exists);
            Assert.IsTrue(Directory.Exists(fullPath));
            Assert.AreEqual(initialSubfoldersCount + 1, FixtureRootRepoFolder.SubFolders.Count());

            string customPropertyName  = "CustomProperty1";
            string customPropertyValue = "CustomPropertyValue1";

            subfolder1.Properties.SetCustomProperty(customPropertyName, "CustomPropertyValue1");
            subfolder1.Properties.Load();
            Assert.AreEqual(customPropertyValue, subfolder1.Properties.GetCustomProperty(customPropertyName)
                            , "Custom property value not persisted");

            IRepositoryWriter writer = subfolder1.GetWriter();

            writer.AllowSubfoldersCreation = true;

            Populate(writer, 100);

            writer.Close();

            subfolder1.Delete(true, true);
            Assert.IsFalse(Directory.Exists(fullPath), "Directory not removed from disk");
            Assert.AreEqual(initialSubfoldersCount, FixtureRootRepoFolder.SubFolders.Count);
        }
Example #7
0
 /// <summary>
 ///		Add a folder to the list of folders being read and prepare it for reading from the specified position
 /// </summary>
 /// <param name="folder">
 ///		Repository folder
 /// </param>
 /// <param name="seekTime">
 ///		Seek timestamp for the folder
 /// </param>
 /// <returns>
 ///		<see langword="false"/> - the folder is already being read
 ///		<see langword="true"/> otherwise
 /// </returns>
 /// <remarks>
 ///		Any subsequent Seek overrides the position used here
 /// </remarks>
 /// <exception cref="ObjectDisposedException">
 ///		The reader has been disposed.
 /// </exception>
 public bool AddFolder(IRepositoryFolder folder, DateTime seekTime)
 {
     CheckNotDisposed();
     Exceptions.DifferentRepositoriesExceptionHelper.Check(folder.Repository, Repository);
     // all additions should go through AddFolderImpl
     return(AddFolderImpl(folder, new FolderReadingPosition(folder, seekTime)));
 }
Example #8
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);
        }
 /// <summary>
 ///		Create new instance.
 /// </summary>
 /// <param name="targetFolder">
 ///		Target repository folder.
 /// </param>
 /// <param name="backwards">
 ///		Whether to iterate backwards.
 /// </param>
 /// <exception cref="ObjectDisposedException">
 ///		The target repository instance is disposed.
 /// </exception>
 /// <exception cref="InvalidOperationException">
 ///		The <paramref name="targetFolder"/> is detached.
 /// </exception>
 public DataFileIterator(IRepositoryFolder targetFolder, bool backwards)
 {
     RepositoryFolder.CheckNotDetached(targetFolder);
     _targetFolder = RepositoryFolder.CastFolder(targetFolder);
     _backwards    = backwards;
     Current       = NextForward = NextBackwards = Next = Previous = null;
 }
Example #10
0
        private static List <T> GetDataAccessors <T>(
            LinkedList <Util.WeakReferenceT <T> > list
            , IRepositoryFolder folder
            , bool subtree
            , bool firstOnly)
            where T : class, IRepositoryDataAccessor
        {
            List <T> retval = new List <T>();

            for (LinkedListNode <Util.WeakReferenceT <T> > node = list.First; node != null;)
            {
                LinkedListNode <Util.WeakReferenceT <T> > nextNode = node.Next;
                IRepositoryDataAccessor accessor = node.Value.Target;
                if (accessor == null)
                {
                    _logger.Info("Purging dead accessor");
                    list.Remove(node);
                }
                else
                {
                    if (accessor.IsAccessing(RepositoryFolder.CastFolder(folder, "folder"), subtree))
                    {
                        _logger.InfoFormat("GetDataAccessors found alive writer for {0}", folder.LogicalPath);
                        retval.Add((T)accessor);
                        if (firstOnly)
                        {
                            break;
                        }
                    }
                }
                node = nextNode;
            }
            return(retval);
        }
 /// <summary>
 ///		Method called from <see cref="Write(IDataItem)"/>
 /// </summary>
 /// <param name="folder">
 ///		Repository folder into which new data item has been added
 /// </param>
 /// <param name="file">
 ///		The data file the data item is going to go to.
 /// </param>
 /// <param name="dataItem">
 ///		The new data item
 /// </param>
 protected virtual void OnDataItemAdded(IRepositoryFolder folder, IRepositoryFileName file, IDataItem dataItem)
 {
     if (!_itemAddedEvent.HasNoSubscribers)
     {
         _itemAddedEvent.Raise(this, new bfs.Repository.Events.DataItemAddedEventArgs(folder, file, dataItem));
     }
 }
        public void AddToReaderTest()
        {
            string name    = "AddToReaderTest";
            string subName = "SubName";

            IRepositoryFolder target    = FixtureRootRepoFolder.CreateSubfolder(name);
            IRepositoryFolder subFolder = target.CreateSubfolder(subName);

            //-----------------------------------

            Mock.RepositoryReaderMock mockedReader = new Mock.RepositoryReaderMock();
            target.AddToReader(mockedReader, false);
            Assert.AreEqual(1, mockedReader.AddFolderCalled);
            Assert.AreSame(mockedReader.LastFolderArgument, target);

            mockedReader.Reset();

            target.AddToReader(mockedReader, true);
            Assert.AreEqual(2, mockedReader.AddFolderCalled);
            Assert.IsTrue(mockedReader.FolderArguments.Contains(target));
            Assert.IsTrue(mockedReader.FolderArguments.Contains(subFolder));

            //------------------------------------
            //now real reader

            IRepositoryReader reader = Repository.RootFolder.GetReader(DateTime.Now.AddDays(-1), false);

            Assert.AreEqual(1, reader.Folders.Count, "Reader just created from a folder");

            target.AddToReader(reader, false);

            Assert.AreEqual(2, reader.Folders.Count, "Another reader added");
        }
Example #13
0
 /// <summary>
 ///     Create and initialize new instance.
 /// </summary>
 /// <param name="folder">
 ///     Repository folder to which a new data item has been added.
 /// </param>
 /// <param name="file">
 ///     Repository file to which a new data item has been added.
 /// </param>
 /// <param name="dataItem">
 ///     Newly added data item.
 /// </param>
 public DataItemAddedEventArgs(
     IRepositoryFolder folder
     , IRepositoryFileName file
     , IDataItem dataItem)
 {
     this.Folder   = folder;
     this.File     = file;
     this.DataItem = dataItem;
 }
Example #14
0
        public void ReadEmptyFolderTest()
        {
            string            targetFolderName = "ReadEmptyFolderTest";
            IRepositoryFolder targetFolder     = FixtureRootRepoFolder.CreateSubfolder(targetFolderName);

            using (IRepositoryReader target = targetFolder.GetReader(DateTime.MinValue, true))
            {
                Assert.IsFalse(target.HasData);
            }
        }
        private ICoder GetEncryptor(IRepositoryFolder targetFolder)
        {
            ICoder retval = null;

            if (targetFolder.Properties.EnableEncryption.HasValue && targetFolder.Properties.EnableEncryption.Value)
            {
                retval = Repository.ObjectFactory.GetEncryptor(targetFolder.Properties.Encryptor);
            }
            return(retval);
        }
Example #16
0
        /// <summary>
        ///		Create exception instance for when timestamp of the last data item read from a data file does not match the border timestamp
        ///		recorded in the file name instance.
        /// </summary>
        /// <param name="folder">
        ///		The target folder containig the data file.
        /// </param>
        /// <param name="fileName">
        ///		The file name as presented by the file name instance contained in the repository object model
        /// </param>
        /// <param name="expectedTime">
        ///		The border timestamp as recorded in the file name instance.
        /// </param>
        /// <param name="actualTime">
        ///		The actual timestamp of the last data item in the file.
        /// </param>
        /// <returns>
        ///		New <see cref="ConcurrencyException"/> instance.
        /// </returns>
        public static ConcurrencyException GetLastReadItemTimestampMismatch(IRepositoryFolder folder, string fileName, DateTime expectedTime, DateTime actualTime)
        {
            string message = string.Format(
                Storage.StorageResources.ReaderLastItemTimeInFileMismatch
                , folder.LogicalPath
                , fileName
                , expectedTime
                , actualTime);

            return(new ConcurrencyException(folder, Storage.StorageResources.PotentialConcurrencyIssueMessage, message, null));
        }
Example #17
0
        /// <summary>
        ///		Add folder and restore its reading position. Folder is identified by its <see cref="IRepositoryFolder.FolderKey"/>
        ///		, which is specified by <see cref="IFolderReadingPosition.FolderKey"/>
        /// </summary>
        /// <param name="folderPosition">
        ///		Folder reading position
        /// </param>
        /// <returns>
        ///		<see langword="true"/> - success
        ///		<see langword="false"/> - folder is already being read
        /// </returns>
        /// <exception cref="ObjectDisposedException">
        ///		The reader has been disposed.
        /// </exception>
        public bool AddFolder(IFolderReadingPosition folderPosition)
        {
            CheckNotDisposed();
            Check.DoRequireArgumentNotNull(folderPosition, "folderPosition");
            IRepositoryFolder folder = Repository.RootFolder.GetDescendant(folderPosition.FolderKey, false);

            Check.DoAssertLambda(folder != null
                                 , () => new ArgumentException(string.Format(StorageResources.FolderNotFound, folderPosition.FolderKey)));

            return(AddFolderImpl(folder, folderPosition));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="targetFolder"></param>
        /// <remarks>
        ///     Constructor is internal because all readers and writers are created in the <see cref="IRepositoryManager.Objectactory />
        ///     to be able to handle concurrency and provide own/different implementation.
        /// </remarks>
        internal FolderDataAccessor(IRepositoryFolder targetFolder)
        {
            Check.DoRequireArgumentNotNull(targetFolder, "targetFolder");
            Check.DoAssertLambda(!targetFolder.IsDetached, () => new ArgumentException(StorageResources.FolderIsNotPartOfARepository));

            _targetFolder = RepositoryFolder.CastFolder(targetFolder);

            _iterator = Repository.ObjectFactory.GetDataFileIterator(targetFolder, false);

            Check.Ensure(Repository.IsDataBeingAccessed(Folder, false));
        }
Example #19
0
        /// <summary>
        ///		Get writer preconfigured to track unsaved changes and allow subfolders creation and targeting
        ///		child folder named <paramref name="targetFolderName"/> of <see cref="FixtureRootRepoFolder"/>
        /// </summary>
        public IRepositoryWriter GetStandaloneWriter(string targetFolderName, int desiredFileSize, IDataRouter router)
        {
            IRepositoryManager manager = GetStandaloneRepository();

            manager.Settings.StorageTransactionSettings = StorageTransactionSettings.RequireTransactions | StorageTransactionSettings.DisallowJoiningAmbientManaged;

            IRepositoryFolder targetFolder = manager.RootFolder.GetDescendant(FixtureRootRepoFolder.LogicalPath, false).GetSubFolder(targetFolderName);

            targetFolder.Properties.DesiredItemsPerFile = desiredFileSize;

            return(GetWriter(targetFolder: targetFolder, router: router));
        }
        /// <summary>
        ///		Write data item to repository
        /// </summary>
        /// <param name="dataItem">
        ///		Data item to write. Must be serializable.
        /// </param>
        /// <remarks>
        ///		The <paramref name="dataItem"/> needs to be serializable employing either automatic or custom serialization. Automatic serialization
        ///		requires only <see cref="SerializableAttribute"/>, but it may be difficult to implement versioning. With custom serialization
        ///		the class has to implement the <see cref="ISerializable"/> interface and a special constructor. Note that no immediate check is performed
        ///		in this method and if the <paramref name="dataItem"/> is not serializable the subsequent flushing of the data to disk may fail.
        ///		Not thread safe, must not be used in more than 1 thread at once.
        /// </remarks>
        public void Write(IDataItem dataItem)
        {
            CheckNotDisposed();
            Check.DoRequireArgumentNotNull(dataItem, "dataItem");

            Check.DoRequire(dataItem.RelativePath != null, "RelativePath must not be null");

            Check.Invariant(_activeDataRouter != null);

            // if new transaction scope is created for ambient managed here and the transaction gets disposed
            using (var scope = _transactionManager.GetLazyTransactionScope())
            {
                DirectSingleFolderWriter targetWriter;
                // relative path as directed by active router
                string originalRelativePath = _activeDataRouter.GetRelativePath(dataItem);

                // have a look at exact match in the cache
                targetWriter = GetExistingWriterByRelativePath(originalRelativePath);
                if (null == targetWriter)
                {
                    // no exact match, let's normalise path
                    string normalizedRelativePath = RepositoryFolder.GetFolderPathKey(originalRelativePath);

                    if (!string.Equals(normalizedRelativePath, originalRelativePath, StringComparison.Ordinal))
                    {
                        targetWriter = GetExistingWriterByRelativePath(normalizedRelativePath);
                    }
                    // if normilised is the same as original  or not same but still there's no writer in cache
                    if (null == targetWriter)
                    {
                        // writing to the folder for the first time
                        // using original relative path to preserve casing when creating
                        IRepositoryFolder targetFolder = GetSubfolder(originalRelativePath, this.AllowSubfoldersCreation);

                        if (null == targetFolder)
                        {
                            throw FolderNotFoundExceptionHelper.GetForWriter(this.Folder, originalRelativePath);
                        }

                        targetWriter = CreateWriter(targetFolder, normalizedRelativePath);
                    }
                }

                Check.Ensure(targetWriter.TrackUnsavedItems == this.TrackUnsavedItems);

                targetWriter.Write(dataItem);

                OnDataItemAdded(targetWriter.Folder, targetWriter.CurrentFile, dataItem);

                scope.Complete();
            }
        }
Example #21
0
        /// <summary>
        ///		Get reader for this repository
        /// </summary>
        /// <param name="targetFolder">
        ///		Target folder to read. Specify <see langword="null"/> to add target folders later.
        /// </param>
        /// <returns>
        ///		New instance of repository reader.
        /// </returns>
        public virtual IRepositoryReader GetReader(IRepositoryFolder targetFolder)
        {
            CheckHelper.CheckRepositoryNotDisposed(Repository);

            IRepositoryReader retval = new RepositoryReader(Repository);

            Repository.RegisterReader(retval);
            if (null != targetFolder)
            {
                retval.AddFolder(targetFolder);
            }

            return(retval);
        }
Example #22
0
        /// <summary>
        ///		Add a folder to the list of folders being read and prepare it for reading if the reader has data
        /// </summary>
        /// <param name="folder">
        ///		Repository folder
        /// </param>
        /// <returns>
        ///		<see langword="false"/> - the folder is already being read
        ///		<see langword="true"/> otherwise
        /// </returns>
        /// <remarks>
        ///		Starting new folder from last read item time, not next item time to be consistent
        ///		if no items has been read yet, using last seek time; this works transparently with restoring position;
        ///		say a reader was sought but there was no data or reading was interrupted; the reader should provide a position
        ///		upon restoration of which later all items added since the position was saved and which would have been read
        ///		had the seek been called after they were added, would be read by the reader.
        /// </remarks>
        /// <exception cref="ObjectDisposedException">
        ///		The reader has been disposed.
        /// </exception>
        public bool AddFolder(IRepositoryFolder folder)
        {
            CheckNotDisposed();
            Exceptions.DifferentRepositoriesExceptionHelper.Check(folder.Repository, Repository);
            // position if reading is under way; otherwise Seek will have to be called before reading
            // all additions should go through AddFolderImpl
            FolderReadingPosition position = null;

            if (IsPositioned)
            {
                position = new FolderReadingPosition(folder, _position.Time);
            }
            return(AddFolderImpl(folder, position));
        }
        public void GetUnsavedItemsWithFlushTest()
        {
            const int subfolderCount = 3;

            string subFolderName = "GetUnsavedItemsTest";

            IRepositoryFolder targetFolder = FixtureRootRepoFolder.CreateSubfolder(subFolderName);

            IRepositoryWriter writer = targetFolder.GetWriter();

            IDataRouter dataRouter = new Mock.NumberedDataRouter(subfolderCount);

            writer.DataRouter = dataRouter;
            writer.AllowSubfoldersCreation = true;

            string fullPath = targetFolder.FullPath;

            Mock.TestDataItem item;

            int lastFlushCount = 0;

            for (int n = 0; n < 10000; ++n)
            {
                item = Mock.TestDataItem.GetTestItem(n);
                writer.Write(item);

                if ((n + 1) % 10 == 0)
                {
                    IDictionary <string, IList <IDataItem> > unsavedItems = writer.GetUnsavedItems();
                    Assert.IsNotNull(unsavedItems);
                    Assert.AreEqual(Math.Min(n + 1, subfolderCount), unsavedItems.Count, "Unsaved items dictionary entry count is not equal to the direct writers count");

                    Assert.AreEqual(n + 1 - lastFlushCount, unsavedItems.Values.Sum((l) => l.Count), "Total number of unsaved items incorrect");
                }
                else if ((n + 1) % 134 == 0)
                {
                    writer.Flush();
                    lastFlushCount = n + 1;

                    IDictionary <string, IList <IDataItem> > unsavedItems = writer.GetUnsavedItems();
                    Assert.IsNotNull(unsavedItems);
                    Assert.AreEqual(Math.Min(n + 1, subfolderCount), unsavedItems.Count, "Unsaved items dictionary entry count is not equal to the direct writers count");

                    Assert.AreEqual(0, unsavedItems.Values.Sum((l) => l.Count), "Total number of unsaved items after flush must be 0");
                }
            }

            writer.Close();
        }
Example #24
0
 /// <summary>
 ///		Get existing readers from either the specified folder or any of its descendants, depending on the parameter
 /// </summary>
 /// <param name="folder">
 ///		<see cref="IRepositoryFolder"/> instance representing the folder or the whole subtree
 ///		(the folder and all its descendants), depending on <paramref name="subtree"/>
 /// </param>
 /// <param name="subtree">
 ///		the scope of the search - <code>bool</code> indicating whether to find writer to any of the descendants of
 ///		<paramref name="folder"/> (<see langword="true"/>) or just <paramref name="folder"/> itself.
 /// </param>
 /// <returns>
 ///		The list of existing readers, never <see langword="null"/>
 /// </returns>
 /// <exception cref="ArgumentException">
 ///		The <paramref name="folder"/> does not belong to this repository
 /// </exception>
 /// <remarks>
 ///		Access to readers and writers registry is synchronised; all concurrent calls accessing registry of readers and writers
 ///		will wait until this method finishes.
 /// </remarks>
 public IList <IRepositoryDataAccessor> GetReaders(IRepositoryFolder folder, bool subtree)
 {
     CheckNotDisposed();
     Check.DoRequireArgumentNotNull(folder, "folder");
     Exceptions.DifferentRepositoriesExceptionHelper.Check(this, folder.Repository);
     _dataAccessorRegistryLock.EnterReadLock();
     try
     {
         return(GetDataAccessors(_readers, folder, subtree, false));
     }
     finally
     {
         _dataAccessorRegistryLock.ExitReadLock();
     }
 }
Example #25
0
        //------------------------------------------------------------------

        /// <summary>
        ///		Get writer preconfigured to track unsaved changes and allow subfolders creation
        /// </summary>
        /// <param name="targetFolder"></param>
        /// <param name="desiredFileSize"></param>
        /// <param name="router"></param>
        /// <returns></returns>
        public IRepositoryWriter GetWriter(IRepositoryFolder targetFolder, IDataRouter router)
        {
            IRepositoryWriter writer = targetFolder.GetWriter();

            writer.TrackUnsavedItems = true;

            if (router != null)
            {
                writer.DataRouter = router;
            }

            writer.AllowSubfoldersCreation = true;

            return(writer);
        }
        private void CheckAllDataInFolder(IRepositoryFolder folder, IDataItem[] expectedData)
        {
            List <IDataItem> dataRead = new List <IDataItem>(expectedData.Length);

            using (IRepositoryReader reader = folder.GetReader(DateTime.MinValue, true))
            {
                while (reader.HasData)
                {
                    dataRead.Add(reader.Read().DataItem);
                }
            }
            Assert.AreEqual(expectedData.Length, dataRead.Count, "The total number of items read after writing does not match the amount written");
            for (int n = 0; n < expectedData.Length; ++n)
            {
                Assert.AreEqual(expectedData[n], dataRead[n]);
            }
        }
Example #27
0
        public void QuickIntegrationTest()
        {
            IRepositoryFolder targetFolder = FixtureRootRepoFolder;
            IDataFileIterator iterator     = Repository.ObjectFactory.GetDataFileIterator(targetFolder, false);

            // this must guarantee that previous, current and next are all not null
            DateTime seekTime = _firstDataItemTime.AddDays(_daysPerFile * 3);

            iterator.Seek(seekTime);
            Assert.IsNotNull(iterator.Current);
            Assert.IsNotNull(iterator.NextBackwards);
            Assert.IsNotNull(iterator.NextForward);

            Assert.IsTrue(iterator.Current.Name.End > seekTime);
            Assert.IsTrue(iterator.NextBackwards.Name.End <= seekTime);
            Assert.IsTrue(iterator.NextForward.Name.FirstItemTimestamp > seekTime);
        }
Example #28
0
        public static FolderNotFoundException GetForWriter(
            IRepositoryFolder writersTarget, string originalRelativePath)
        {
            string message       = string.Format(Storage.StorageResources.DescendantFolderNotFound, originalRelativePath, writersTarget.LogicalPath);
            string technicalInfo = string.Format(
                @"Target folder was not found by its relative path {0}
in forlder {1}
repository {2}"
                , originalRelativePath
                , writersTarget.LogicalPath
                , writersTarget.Repository.RepositoryRoot);

            return(new FolderNotFoundException(
                       message: message
                       , technicalInfo: technicalInfo
                       , rootRepositoryPath: writersTarget.Repository.RepositoryRoot
                       , pathToTargetFolder: originalRelativePath
                       , innerException: null));
        }
Example #29
0
        /// <summary>
        ///		Get writer for this repository
        /// </summary>
        /// <param name="targetFolder">
        ///		Target root folder to write. Data items may go to descendants folders,
        ///		<see cref="bfs.Repository.Interfaces.IDataItem.RelativePath"/>
        /// </param>
        /// <returns>
        ///		New instance of <see cref="IRepositoryWriter"/>.
        /// </returns>
        /// <remarks>
        ///     Only 1 writer can be created for a particular folder.
        /// </remarks>
        public virtual IRepositoryWriter GetWriter(IRepositoryFolder targetFolder)
        {
            CheckHelper.CheckRepositoryNotDisposed(Repository);
            Check.RequireArgumentNotNull(targetFolder, "targetFolder");

            RepositoryWriter retval;

            lock (targetFolder)
            {
                RepositoryFolder.CheckNotDetached(targetFolder);

                Check.DoAssertLambda(!Repository.IsDataBeingWrittenTo(targetFolder, false),
                                     () => new InvalidOperationException(string.Format(StorageResources.WriterAlreadyExistsForFolder, targetFolder.LogicalPath)));

                retval = new RepositoryWriter(RepositoryFolder.CastFolder(targetFolder));
                Repository.RegisterWriter(retval);
            }
            Check.Ensure(Repository.IsDataBeingWrittenTo(targetFolder, false));
            return(retval);
        }
        public void WriteTest()
        {
            string subFolderName = "WriteTest";

            int initialSubfoldersCount = Repository.RootFolder.SubFolders.Count;

            IRepositoryFolder targetFolder = FixtureRootRepoFolder.CreateSubfolder(subFolderName);

            IRepositoryWriter writer = targetFolder.GetWriter();

            writer.AllowSubfoldersCreation = true;

            string fullPath = targetFolder.FullPath;

            Mock.TestDataItem item;

            for (int n = 0; n < 100; ++n)
            {
                item = Mock.TestDataItem.GetTestItem(n);
                writer.Write(item);
            }

            // testing automatic subfolder creation
            item = Mock.TestDataItem.GetTestItem(1000);

            item.RelativePath = "AutoSubfolder1/Auto2";

            writer.Write(item);

            Assert.AreEqual(1, targetFolder.SubFolders.Count, "Automatic subfolder creation during write failed");
            Assert.IsNotNull(targetFolder.GetSubFolder("AutoSubfolder1"));
            Assert.AreEqual(1, targetFolder.GetSubFolder("AutoSubfolder1").SubFolders.Count);
            Assert.IsNotNull(targetFolder.GetSubFolder("AutoSubfolder1").GetSubFolder("Auto2"));

            writer.Flush();
            writer.Close();

            targetFolder.Delete(true, true);
            Assert.IsFalse(Directory.Exists(fullPath), "Directory not removed from disk");
            Assert.AreEqual(initialSubfoldersCount, Repository.RootFolder.SubFolders.Count);
        }