/// <summary> /// Initializes a new instance of the <see cref="SubdirectoryFileSystem"/> class /// </summary> /// <param name="parentFileSystem">The file system to represent a subdirectory of.</param> /// <param name="dataStorePath">The (data store) path of the directory to represent.</param> public SubdirectoryFileSystem( IFileSystem parentFileSystem, string dataStorePath ) { try { if( parentFileSystem.NullReference() ) throw new ArgumentNullException().StoreFileLine(); if( !DataStore.IsValidPath(dataStorePath) ) // empty string is acceptable! throw new ArgumentException().StoreFileLine(); this.parentFileSystem = parentFileSystem; this.subDirPath = dataStorePath; } catch( Exception ex ) { ex.StoreFileLine(); ex.Store("parentFileSystemType", parentFileSystem.NullReference() ? null : parentFileSystem.GetType()); ex.Store("dataStorePath", dataStorePath); throw; } }
/// <summary> /// Returns all files recently created by this app instance. /// The results are in descending order (according to creation time). /// </summary> /// <param name="fileSystem">The abstract file system to search the root directory of.</param> /// <param name="maxFileAge">The maximum age of the files returned, or <c>null</c>.</param> /// <param name="maxAppInstanceCount">The maximum number of app instances to include, or <c>null</c>.</param> /// <param name="maxTotalFileSize">The maximum total file size, or <c>null</c>.</param> /// <returns>All files recently created by this app instance.</returns> public static ProlificDataFileInfo[] FindLatestFiles( IFileSystem fileSystem, TimeSpan? maxFileAge, int? maxAppInstanceCount, long? maxTotalFileSize ) { if( fileSystem.NullReference() ) throw new ArgumentNullException().StoreFileLine(); if( maxFileAge.HasValue && maxFileAge.Value.Ticks < 0 ) throw new ArgumentOutOfRangeException().Store("maxFileAge", maxFileAge); if( maxAppInstanceCount.HasValue && maxAppInstanceCount.Value < 0 ) throw new ArgumentOutOfRangeException().Store("maxAppInstanceCount", maxAppInstanceCount); if( maxTotalFileSize.HasValue ) { if( maxTotalFileSize.Value < 0 ) throw new ArgumentOutOfRangeException().Store("maxTotalFileSize", maxTotalFileSize); if( !fileSystem.SupportsGetFileSize ) throw new NotSupportedException("The specified file system does not support GetFileSize!").StoreFileLine(); } // sort in descending order by CreationTime var files = FindAllFiles(fileSystem).ToList(); files.Sort(( x, y ) => y.CreationTime.CompareTo(x.CreationTime)); // determine the minimum CreationTime (if there is one) DateTime? minTime = null; if( maxFileAge.HasValue ) minTime = DateTime.UtcNow - maxFileAge.Value; HashSet<string> appInstancesAllowed = null; if( maxAppInstanceCount.HasValue ) appInstancesAllowed = new HashSet<string>(AppInstanceIDComparer); long totalFileSize = 0; long currentFileSize; ProlificDataFileInfo fileInfo; for( int i = 0; i < files.Count; ) { fileInfo = files[i]; // too old? if( minTime.HasValue && fileInfo.CreationTime < minTime ) { files.RemoveAt(i); continue; } // too many app instances? if( maxAppInstanceCount.HasValue && !appInstancesAllowed.Contains(fileInfo.AppInstanceID) ) { if( appInstancesAllowed.Count < maxAppInstanceCount.Value ) { //// there is still room for one more app instance, //// but we do not record the new app instance ID here, //// since another rule may still throw this file out... } else { // a yet unseen app instance ID, but we have no more room for it files.RemoveAt(i); continue; } } // too many bytes? if( maxTotalFileSize.HasValue ) { currentFileSize = fileSystem.GetFileSize(fileInfo.DataStoreName); if( totalFileSize + currentFileSize > maxTotalFileSize.Value ) { // adding this file would exceed the file size limit, so we'll skip it files.RemoveAt(i); // we will also raise the total file size recorded beyond the maximum: // it could be possible that later there would be a file small // enough to still fit in, but an unbroken time line seems more // important than cramming as many bytes in as possible... // It's just a feeling though, maybe this is stupid :) totalFileSize = maxTotalFileSize.Value + 1; continue; } else { //// there is still room for these bytes, //// but we do not update the total file size here, //// since another rule may still throw this file out... //// (one added at a later time) } } else currentFileSize = 0; // no rule removed this file: update variables and continue appInstancesAllowed.Add(fileInfo.AppInstanceID); totalFileSize += currentFileSize; ++i; } return files.ToArray(); }
/// <summary> /// Finds all data files in the root of the specified file system. The result is unsorted. /// </summary> /// <param name="fileSystem">The abstract file system to search the root directory of.</param> /// <returns>All data files found.</returns> public static ProlificDataFileInfo[] FindAllFiles( IFileSystem fileSystem ) { if( fileSystem.NullReference() ) throw new ArgumentNullException().StoreFileLine(); var fileDataStoreNames = fileSystem.GetFileNames(); var results = new List<ProlificDataFileInfo>(); ProlificDataFileInfo fileInfo; foreach( var name in fileDataStoreNames ) { if( TryParseDataStoreName(name, fileSystem.EscapesNames, out fileInfo) ) results.Add(fileInfo); } return results.ToArray(); }