/// <summary> /// Create data file accessor instance. /// </summary> /// <param name="folder"> /// Data folder containig the file. /// </param> /// <param name="file"> /// Data file to be accessed; may not exist on disk. /// </param> /// <returns> /// New <see cref="IDataFileAccessor"/> instance. /// </returns> public IDataFileAccessor GetDataFileAccessor(IDataFolder folder, IRepositoryFileName file) { Check.DoRequireArgumentNotNull(folder, "folder"); Check.DoRequireArgumentNotNull(file, "file"); RepositoryFolder.CheckNotDetached(folder.RepoFolder); return(new RepositoryFileAccessor(folder, file)); }
/// <summary> /// Create new instance. /// </summary> /// <param name="containingFolder"> /// Leaf data folder object reference, mandatory. /// </param> /// <param name="fileName"> /// Object representing data file name, optional. /// </param> public RepositoryFile(IDataFolder containingFolder, IRepositoryFileName fileName) { Check.DoRequireArgumentNotNull(containingFolder, "containingFolder"); RepositoryFolder.CheckNotDetached(containingFolder.RepoFolder); ContainingFolder = containingFolder; Name = fileName; }
public RaceJsonRepository(IDataFolder dataFolder) { this.dataFolder = dataFolder; this.mutex = new ReaderWriterLockSlim(); this.serializer = JsonSerializer.CreateDefault(); this.serializer.Converters.Add(new SexJsonConverter()); this.raceData = null; }
/// <summary> /// Discarding changes if dirty. Call <see cref="Flush"/> to save changes. /// </summary> public void Close() { FirstItemTimestamp = DateTime.MaxValue; LastItemTimestamp = DateTime.MinValue; _existinglFilePath = null; _dataItems = null; _dataFolder = null; _repoFile = null; }
/// <summary> /// Create accessor for a file and retrieve compressor from repository's /// object factory by the file extension /// </summary> /// <param name="folder"> /// Containing repo folder /// </param> /// <param name="repoFile"> /// Target data file, optional. /// </param> /// <param name="dataFolder"> /// Leaf data folder containing <paramref name="repoFile"/> /// </param> /// <param name="equalTimestampedItemsComparer"> /// Comparer for data items with equal timestamps, optional. /// </param> internal RepositoryFileAccessor( IFolder folder , IRepositoryFileName repoFile , IDataFolder dataFolder , IComparer <IDataItem> equalTimestampedItemsComparer) : this(dataFolder, repoFile , folder.Repository.ObjectFactory.GetCompressor(repoFile.CompressorCode) , equalTimestampedItemsComparer) { }
public AthletesJsonRepository(IDataFolder dataFolder) { this.dataFolder = dataFolder; this.mutex = new ReaderWriterLockSlim(); this.allAthletesIds = null; this.individualAthletes = new Dictionary <string, Athlete>(); this.serializer = JsonSerializer.CreateDefault(); this.serializer.Converters.Add(new SexJsonConverter()); this.serializer.Converters.Add(new CardResultJsonConverter()); }
public JudgesJsonRepository(IDataFolder dataFolder) { this.dataFolder = dataFolder; this.mutex = new ReaderWriterLockSlim(); this.isLoaded = false; this.judgesById = new Dictionary <string, Judge>(); this.devicesById = new Dictionary <string, JudgeDevice>(); this.devicesByConnectCode = new Dictionary <string, JudgeDevice>(); this.authenticationMap = new Dictionary <string, string>(); this.serializer = JsonSerializer.CreateDefault(); }
/// <summary> /// Find a place for data item with the specified timestamp /// </summary> /// <exception cref="System.IO.FileNotFoundException"> /// File found in the data file container was not found on disk, by virtue of <see cref="RepositoryFileAccessor.ReadFromFile"/>. /// Possible concurrent update; better shut down. /// </exception> private void Seek(DateTime seekTimestamp) { if (null == _currentFolder || !IsCovering(_currentFolder, seekTimestamp)) { // need to change current leaf data folder _currentFolder = _targetFolder.RootDataFolder.GetLeafFolder(seekTimestamp, true); } IRepositoryFileName targetFile; IRepositoryFileName predecessor; IRepositoryFileName successor; _currentFolder.DataFileBrowser.GetDataFiles(seekTimestamp, out predecessor, out targetFile, out successor); bool openingExistingFile = targetFile != null; if (!openingExistingFile) { // new file needed targetFile = _targetFolder.Repository.ObjectFactory.CreateNewFile(_targetFolder); } _currentAccessor = GetAccessor(targetFile); if (openingExistingFile) { // will throw exception if file was not found or failed to read _currentAccessor.ReadFromFile(); } _currentAccessor.Encryptor = this.Encryptor; // set timestamp limits if (null != predecessor) { _currentAccessor.MinTimestampToAccept = predecessor.LastItemTimestamp.AddTicks(1); } else { _currentAccessor.MinTimestampToAccept = _currentFolder.Start; } if (null != successor) { _currentAccessor.MaxTimestampToAccept = successor.FirstItemTimestamp.AddTicks(-1); } else { _currentAccessor.MaxTimestampToAccept = _currentFolder.End.AddTicks(-1); } Check.Ensure(null != _currentAccessor); }
/// <summary> /// Get child data folder which next to the specified child folder. /// </summary> /// <param name="childFolder"> /// The child folder which neighbour to find /// </param> /// <param name="backwards"> /// Whether to find next folder older than the <paramref name="childFolder"/> (<see langword="true"/>) /// or newer (<see langword="false"/>). Older means smaller timestamp. /// </param> /// <returns> /// Existing data folder which is a child of this data folder or <see langword="null"/> if the sought data folder /// does not exist. /// </returns> public IDataFolder GetNextChild(IDataFolder childFolder, bool backwards) { LoadSubFolders(false); if (backwards) { return(_childDataFolders.GetPredecessor(childFolder.Start)); } else { // GetSuccessor accepts item key, adjusting End as it's exclusive return(_childDataFolders.GetSuccessor(childFolder.End.AddTicks(-1))); } }
/// <summary> /// Read the list of immediately contained subfolders /// from disk. /// For leaf folders does nothing. /// </summary> /// <param name="reloadIfLoaded"></param> public void LoadSubFolders(bool reloadIfLoaded) { Invariant(); if (!this.IsLeafFolder) { if (!this.SubfoldersLoaded || reloadIfLoaded) { _log.DebugFormat("LoadSubFolders: Scanning <{0}> for subfolders", RelativePath); // in the year-month scheme this will be year or root data folder // i.e. _repoFolder.DataFoldersExplorer will be parent at most // note that current implementation requires this to be a child // how will it be affected with the addition of another level? // it will not be valid; need to make it more explicit; there's coupling between DataFolder and folder traits // or, if I add more levels I will need to lift the limitation in DataFoldersExplorer implementation List <IRepoFileContainerDescriptor> subFolders = _repoFolder.DataFoldersExplorer.Enumerate(_folderDescriptor, this.Level - 1); IIndexedRangeCollection <DateTime, IDataFolder> oldList = _childDataFolders; _childDataFolders = new IndexedRangeTreeDictionary <DateTime, IDataFolder>(f => f.Start, f => f.End); foreach (IRepoFileContainerDescriptor descr in subFolders) { _log.DebugFormat("Found subfolder {0}", descr.ToString()); IDataFolder newSubFolder = null; if (null != oldList) { newSubFolder = oldList.GetExact(descr.Start); } if (null == newSubFolder) { newSubFolder = new DataFolder(this, descr); _log.Debug("The found subfolder was not in the list"); } else { _log.Debug("The subfolder was already in the list"); } _childDataFolders.Add(newSubFolder); } } } else { _log.Debug("LoadSubFolders called for leaf folder"); } }
/// <summary> /// Get first (chronologically) descendant at the specified level /// </summary> /// <param name="level"> /// Level at which to find descendant. Must point to a descendant (i.e. be less than <code>this.Level</code> and greater or /// equal to zero (which is leaf level). /// </param> /// <param name="backwards"> /// Whether to find oldest (<see langword="false"/>) or newest (<see langword="true"/>) descendant. /// </param> /// <returns> /// First descendant at <paramref name="level"/> or <see langword="null"/> if none exists. /// </returns> public IDataFolder GetFirstDescendant(int level, bool backwards) { RequireDescendant(level); IDataFolder descendant = GetFirstChildFolder(backwards); if (descendant != null && level < (this.Level - 1)) { descendant = descendant.GetFirstDescendant(level, backwards); } else if (level == (this.Level - 1)) { // reached target level return(descendant); } return(null); }
/// <summary> /// Get first (chronologically) descendant at the specified level /// </summary> /// <param name="dataTimestamp"> /// The start of the time period (inclusive) for which to find covering data folder /// </param> /// <param name="level"> /// Level at which to find descendant. Must point to a descendant (i.e. be less than <code>this.Level</code> and greater or /// equal to zero (which is leaf level). /// </param> /// <param name="backwards"> /// The direction in which the time period goes from <paramref name="dataTimestamp"/> /// </param> /// <returns> /// First descendant at <paramref name="level"/> or <see langword="null"/> if none exists. /// </returns> /// <remarks> /// For example GetFirstDescendant(DateTime.Now, 1, true) will find first existing descendant at level 1 /// which covers time starting from now and going to the past. /// </remarks> public IDataFolder GetFirstDescendant(DateTime dataTimestamp, int level, bool backwards) { RequireDescendant(level); Check.RequireLambda(dataTimestamp >= this.Start && dataTimestamp <= this.End , () => new ArgumentException("The timestamp is outside of the range of the folder", "dataTimestamp")); if (IsChild(level)) { return(GetFirstChildFolder(dataTimestamp, backwards)); } IDataFolder retval = null; var enumerator = GetSubfoldersSequence(dataTimestamp, backwards).GetEnumerator(); if (enumerator.MoveNext()) { if (IsCovering(enumerator.Current, dataTimestamp)) { // enumerator.Current is the "owner" retval = enumerator.Current.GetFirstDescendant(dataTimestamp, level, backwards); } else { // there's no owner, will look for first descendant enumerator.Reset(); } } if (retval == null) { // enumerator will now point past any owner (covering) child folder; so no need to use (filter by) the target timestamp // just find first descendant in those folders; need to enumerate because an existing child folder may not have any // descendants at the target level while (enumerator.MoveNext()) { retval = enumerator.Current.GetFirstDescendant(level, true); if (null != retval) { break; } } } return(retval); }
/// <summary> /// Find existing leaf data folder and [optionally] create if it is /// missing. Primarily intended for use by writers. /// </summary> /// <param name="itemTimestamp"> /// The timestamp of an item for which to find the existing /// or create new leaf folder /// </param> /// <returns> /// Existing leaf folder /// null if the folder is missing and <paramref name="createIfMissing"/> /// is <see langword="false"/> /// </returns> public IDataFolder GetLeafFolder(DateTime itemTimestamp, bool createIfMissing) { IDataFolder retval = null; if (this.IsLeafFolder) { if (this.Start <= itemTimestamp && this.End > itemTimestamp) { retval = this; } } else // if (this.IsLeafFolder) { LoadSubFolders(false); retval = _childDataFolders.GetOwner(itemTimestamp); if (retval == null && createIfMissing) { // creating target subfolder; this will be a child folder of this data folder IRepoFileContainerDescriptor descr = _repoFolder.DataFoldersExplorer.GetTargetFolder( itemTimestamp, this.Level - 1); retval = new DataFolder(this, descr); retval.EnsureDirectoryExists(); _childDataFolders.Add(retval); } if (retval != null) { if (retval.Level > 0) { // not a leaf folder yet - drilling down all the way retval = retval.GetLeafFolder(itemTimestamp, createIfMissing); } } } Check.Ensure(null != retval || !createIfMissing); Check.Ensure(null == retval || retval.IsLeafFolder); Check.Ensure(null == retval || (retval.Start <= itemTimestamp && retval.End > itemTimestamp)); return(retval); }
/// <summary> /// Get successor or predecessor of this folder at the same level of the folders hierarchy /// </summary> /// <param name="backwards"> /// <see langword="true"/> for predecessor /// <see langword="false"/> for successor /// </param> /// <returns> /// <see langword="null"/> if none exist /// </returns> public IDataFolder GetNextSiblingInTree(bool backwards) { Check.RequireLambda(!IsVirtualRoot, () => new InvalidOperationException(StorageResources.VirtualRootInvalidOperation)); IDataFolder retval = ParentDataFolder.GetNextChild(this, backwards); if (null == retval) { if (!ParentDataFolder.IsVirtualRoot) { for ( IDataFolder nst = ParentDataFolder.GetNextSiblingInTree(backwards); nst != null && retval == null; nst = nst.GetNextSiblingInTree(backwards)) { retval = nst.GetFirstChildFolder(backwards); } } } return(retval); }
/// <summary> /// /// </summary> /// <param name="dataFolder"> /// Leaf data folder in which the data files will be accessed. /// </param> /// <param name="repoFile"> /// Target repo file, optional. New instance will be created using object factory if null is supplied. /// </param> /// <param name="coder"> /// Compressor instance /// </param> /// <param name="equalTimestampedItemsComparer"> /// Comparer to use when sorting data items for items with equal timestamps. /// When timestamps are not equal the comparer has no effect. /// </param> internal RepositoryFileAccessor( IDataFolder dataFolder , IRepositoryFileName repoFile , ICoder coder , IComparer <IDataItem> equalTimestampedItemsComparer) { Check.DoRequireArgumentNotNull(dataFolder, "dataFolder"); Check.DoRequireArgumentNotNull(repoFile, "repoFile"); Check.DoRequireArgumentNotNull(coder, "coder"); RepositoryFolder.CheckNotDetached(dataFolder.RepoFolder); _folder = dataFolder.RepoFolder; _repoFile = repoFile; _dataFolder = dataFolder; if (_repoFile == null) { _repoFile = _folder.Repository.ObjectFactory.CreateNewFile(_folder); } this.Coder = coder; if (repoFile.Encrypted) { this.Encryptor = _folder.Repository.ObjectFactory.GetEncryptor(repoFile.EncryptorCode); } if (_folder.Repository.ObjectFactory.FileSystemProvider.FileProvider.Exists(this.FilePath)) { _existinglFilePath = this.FilePath; } else { _dataItems = new List <IDataItem>(); } _isSorted = true; this.EqualTimestampItemsComparer = equalTimestampedItemsComparer; FirstItemTimestamp = DateTime.MaxValue; LastItemTimestamp = DateTime.MinValue; }
/// <summary> /// Cut descendant folders at the specified level. /// </summary> /// <param name="timestamp"> /// Cutting data timesatamp /// </param> /// <param name="level"> /// Level at which to cut. Must point to a descendant (i.e. be less than <see cref="Level"/> and greater or equal to zero /// (which is leaf level). /// </param> /// <param name="predecessor"> /// Output, the existing predecessor at <paramref name="level"/> of a folder, covering <paramref name="timestamp"/>; /// <see langword="null"/> if none exists. /// </param> /// <param name="owner"> /// Output, the data folder at <paramref name="level"/>, covering <paramref name="timestamp"/>. /// <see langword="null"/> if none exists. /// </param> /// <param name="successor"> /// Output, the existing successor at <paramref name="level"/> of a folder, covering <paramref name="timestamp"/>; /// <see langword="null"/> if none exists. /// </param> public void CutDescendantFolders(DateTime timestamp, int level, out IDataFolder predecessor, out IDataFolder owner, out IDataFolder successor) { Check.RequireLambda(level >= 0 && level < this.Level, () => new InvalidOperationException(StorageResources.LevelOfDescendantRequired)); LoadSubFolders(false); predecessor = owner = successor = null; IDataFolder childPredecessor; IDataFolder childOwner; IDataFolder childSuccessor; _childDataFolders.GetItems(timestamp, out childPredecessor, out childOwner, out childSuccessor); if (level < (this.Level - 1)) { // need to dig deeper if (childOwner != null) { childOwner.CutDescendantFolders(timestamp, level, out predecessor, out owner, out successor); } // even if childOwner is found it may not be the root of the subtree containing the predecessor at the specified level // because there may not be existing descendants at that level; if (predecessor == null && childPredecessor != null) { predecessor = GetFirstDescendant(childPredecessor.End.AddTicks(-1), level, true); } if (successor == null && childSuccessor != null) { successor = GetFirstDescendant(childSuccessor.Start, level, false); } } else { predecessor = childPredecessor; owner = childOwner; successor = childSuccessor; } }
/// <summary> /// Get next data file in the same repo folder. /// </summary> /// <param name="backwards"> /// The direction in which to look for data file relative to this file: to the past or to the future /// </param> /// <returns> /// Next data file or <see langword="null"/> if none exists. /// </returns> public IRepositoryFile GetNext(bool backwards) { IRepositoryFile retval = null; IRepositoryFileName fileInSameFolder = ContainingFolder.GetNextDataFile(this.Name, backwards); if (null != fileInSameFolder) { retval = new RepositoryFile(containingFolder: ContainingFolder, fileName: fileInSameFolder); } else { // scanning sibling leaf folders until first data file is found for ( IDataFolder nextFolder = ContainingFolder.GetNextSiblingInTree(backwards); nextFolder != null && retval == null; nextFolder = nextFolder.GetNextSiblingInTree(backwards)) { retval = nextFolder.FindFirstDataFile(backwards); } } return(retval); }
private static bool IsCovering(IDataFolder dataFolder, DateTime itemTimestamp) { return(dataFolder.Start <= itemTimestamp && dataFolder.End > itemTimestamp); }
/// <summary> /// Create new instance. /// </summary> /// <param name="folder"> /// Data folder where file will be stored. /// </param> /// <param name="file"> /// File name instance, optional. /// </param> /// <remarks> /// If <paramref name="file"/> is not supplied new instance will be created using the object factory (<see cref="IRepository.ObjectFactory"/>). /// Coder and encryptor will be set from the object factory as well. They may be overridden afterwards. /// </remarks> public RepositoryFileAccessor(IDataFolder folder, IRepositoryFileName file) : this(folder : folder.RepoFolder, repoFile : file, dataFolder : folder, equalTimestampedItemsComparer : null) { }
/// <summary> /// Real existing data folder /// </summary> /// <param name="parentDataFolder"></param> /// <param name="folderDescriptor"></param> public DataFolder(DataFolder parentDataFolder, IRepoFileContainerDescriptor folderDescriptor) { _parentDataFolder = parentDataFolder; _folderDescriptor = folderDescriptor; _repoFolder = parentDataFolder.RepoFolder; }
public StartingListJsonRepository(IDataFolder dataFolder) { this.dataFolder = dataFolder; this.mutex = new ReaderWriterLockSlim(); this.serializer = JsonSerializer.CreateDefault(); }
public void MyClassInitialize() { lock (GetType()) { if (_emptyDataFolder == null) { const int itemsCount = 100000; _daysPerFile = ((double)_dataItemsPerFile) * _itemsIntervalMinutes / 60.0 / 24.0; // 200 * 20 minutes = 8000 minutes per file (5.55556 days) DateTime firstTime = DateTime.Now.AddDays(-10); _firstDataItemTime = firstTime; //_expectedFileCount = (int)Math.Ceiling((double)itemsCount / (double)_dataItemsPerFile); IFolder targetFolder = (IFolder)FixtureRootRepoFolder; string targetFolderPath = targetFolder.FullPath; targetFolder.Properties.DesiredItemsPerFile = _dataItemsPerFile; using (IRepositoryWriter writer = targetFolder.GetWriter()) { DateTime lastTime = DateTime.MinValue; int n; for (n = 0; n < itemsCount; ++n) { Mock.TestDataItem item = Mock.TestDataItem.GetTestItem(n); lastTime = firstTime.AddMinutes(n * _itemsIntervalMinutes); item.DateTime = lastTime; writer.Write(item); } _lastDataItemTime = lastTime; writer.Flush(); writer.Close(); } for ( var dataFile = targetFolder.RootDataFolder.FindFirstDataFile(false); dataFile != null; dataFile = dataFile.GetNext(false), ++_expectedFileCount ) { } Console.WriteLine("Expected file count enumerated via RepositoryFile: {0}", _expectedFileCount); // data folder boundaries may split data files thus extra ones Assert.GreaterOrEqual(_expectedFileCount, (int)Math.Ceiling((double)itemsCount / (double)_dataItemsPerFile), "Data file count unexpected"); // creating empty folder IRepositoryFile file = targetFolder.RootDataFolder.Seek(firstTime.AddMinutes(itemsCount * _itemsIntervalMinutes / 3), false); _emptyDataFolder = file.ContainingFolder; for ( file = _emptyDataFolder.FindFirstDataFile(false); file != null && file.ContainingFolder == _emptyDataFolder; file = file.GetNext(false)) { file.Delete(); --_expectedFileCount; } Assert.AreEqual(0, _emptyDataFolder.DataFileBrowser.FileCount); Console.WriteLine("Expected file count after removing file by file: {0}", _expectedFileCount); // IDataFolder dfolderToDelete = _emptyDataFolder.ParentDataFolder.GetNextSiblingInTree(false).GetNextSiblingInTree(false); Assert.AreEqual(1, dfolderToDelete.Level); _deletedDataFolder = new RepoFileContainerDescriptor() { Start = dfolderToDelete.Start, End = dfolderToDelete.End, Level = dfolderToDelete.Level, RelativePath = dfolderToDelete.RelativePath }; _expectedFileCount -= dfolderToDelete.GetSubfolders(DateTime.MinValue, false).Sum((f) => f.DataFileBrowser.FileCount); Console.WriteLine("Expected file count after removing data folder {0}: {1}", dfolderToDelete.PathInRepository, _expectedFileCount); Console.WriteLine("Removing folder {0}", dfolderToDelete.PathInRepository); dfolderToDelete.Delete(false); Assert.IsFalse(dfolderToDelete.Exists); } } //lock }
public RepositorySetJsonProvider(IDataFolder rootFolder) { this.rootFolder = rootFolder; }
public SeekFileResult(DateTime seekTime, IDataFolder foundFolder, IRepositoryFileName foundFile) { this.SeekDateTime = seekTime; this.RepositoryFile = new RepositoryFile(containingFolder: foundFolder, fileName: foundFile); }
private bool IsCovering(IDataFolder folder, DateTime timestamp) { return(timestamp >= folder.Start && timestamp < folder.End); }