diff --git a/BITS/BackgroundCopyJob.cs b/BITS/BackgroundCopyJob.cs index 66c890b9..5f655b8e 100644 --- a/BITS/BackgroundCopyJob.cs +++ b/BITS/BackgroundCopyJob.cs @@ -492,6 +492,19 @@ namespace Vanara.IO [DefaultValue(false)] public bool OwnerIsElevated => RunAction(() => IJob4.GetOwnerElevationState()); + /// + /// Gets or sets flags that determine if the files of the job can be cached and served to peers and if BITS can download content for + /// the job from peers. + /// + /// + /// Flags that determine if the files of the job can be cached and served to peers and if BITS can download content for the job from peers. + /// + public PeerCaching PeerCachingEnablment + { + get => (PeerCaching)IJob4.GetPeerCachingFlags(); + set => IJob4.SetPeerCachingFlags((BG_JOB_ENABLE_PEERCACHING)value); + } + /// /// Gets or sets the priority level for the job. The priority level determines when the job is processed relative to other jobs in /// the transfer queue. diff --git a/BITS/BackgroundCopyManager.cs b/BITS/BackgroundCopyManager.cs index c3771ab8..c6609c93 100644 --- a/BITS/BackgroundCopyManager.cs +++ b/BITS/BackgroundCopyManager.cs @@ -50,7 +50,7 @@ namespace Vanara.IO } } - private static IBackgroundCopyManager IMgr => ciMgr.Item; + internal static IBackgroundCopyManager IMgr => ciMgr.Item; /// Copies an existing file to a new file using BITS. Overwriting a file of the same name is not allowed. /// The file to copy. diff --git a/BITS/Enums.cs b/BITS/Enums.cs index 0f3be0f6..57e3302a 100644 --- a/BITS/Enums.cs +++ b/BITS/Enums.cs @@ -157,6 +157,60 @@ namespace Vanara.IO Proxy = BG_AUTH_TARGET.BG_AUTH_TARGET_PROXY } + /// + /// Flags that determine if the files of the job can be cached and served to peers and if BITS can download content for the job from peers. + /// + [Flags] + public enum BackgroundCopyJobEnablePeerCaching + { + /// + /// The job can download content from peers. + /// + /// The job will not download from a peer unless both the client computer and the job allow Background Intelligent Transfer Service + /// (BITS) to download files from a peer. To enable the client computer to download files from a peer, set the EnablePeerCaching + /// group policy or call the property and set the flag. + /// + /// + /// If one of the following conditions exists, BITS will stop the download and reschedule the job to begin transferring from either a + /// peer or the origin server, depending on the value for the job and the cache: + /// + /// + /// + /// + /// This value for the cache is and the value for the job toggles between and . + /// + /// + /// + /// + /// This value for the job property is and the value for the cache toggles between and + /// . + /// + /// + /// + /// The download will then resume from where it left off before BITS stopped the job. + /// BITS 4.0: This flag is deprecated. + /// + EnableClient = BG_JOB_ENABLE_PEERCACHING.BG_JOB_ENABLE_PEERCACHING_CLIENT, + + /// + /// The files of the job can be cached and served to peers. + /// + /// BITS will not cache the files and serve them to peers unless both the client computer and job allow BITS to cache and serve the + /// files. To allow BITS to cache and serve the files on the client computer, set the EnablePeerCaching group policy or call the property and set the flag. + /// + /// BITS 4.0: This flag is deprecated. + /// + EnableServer = BG_JOB_ENABLE_PEERCACHING.BG_JOB_ENABLE_PEERCACHING_SERVER, + + /// + /// BITS will not use Windows BranchCache for transfer jobs. This setting does not affect the use of Windows BranchCache by + /// applications other than BITS. + /// + DisableBranchCache = BG_JOB_ENABLE_PEERCACHING.BG_JOB_DISABLE_BRANCH_CACHE, + } + /// Defines the constant values that specify the priority level of a job. public enum BackgroundCopyJobPriority { @@ -294,4 +348,47 @@ namespace Vanara.IO /// Specifies that the job uploads a file to the server and receives a reply file from the server application. UploadReply = BG_JOB_TYPE.BG_JOB_TYPE_UPLOAD_REPLY } + /// Flags that determine if the computer serves content to peers and can download content from peers. + [Flags] + public enum PeerCaching + { + /// + /// The computer can download content from peers. + /// + /// BITS will not download files from a peer unless both the client computer and the job permit BITS to download files from a peer. + /// To permits the job to download files from a peer, use the property and set + /// the flag. + /// + /// + /// Note that changing this value can affect all jobs on the computer. If one of the following conditions exists, BITS will stop the + /// download and reschedule the job to begin transferring from either a peer or the origin server, depending on the value for the job + /// and the cache: + /// + /// + /// + /// + /// This value for the cache is and the value for the job toggles between and . + /// + /// + /// + /// + /// This value for the job property is and the value for the cache toggles between and + /// . + /// + /// + /// + /// The download will then resume from where it left off before BITS stopped the job. + /// + Enable = BG_ENABLE_PEERCACHING.BG_ENABLE_PEERCACHING_CLIENT, + + /// + /// The computer can serve content to peers. + /// + /// BITS will not cache the files and serve them to peers unless both the client computer and job permit BITS to cache and serve + /// files. To permit the job to cache files for a job, use the property and set + /// the flag. + /// + /// + EnableServer = BG_ENABLE_PEERCACHING.BG_ENABLE_PEERCACHING_SERVER, + } } \ No newline at end of file diff --git a/BITS/PeerCacheAdministration.cs b/BITS/PeerCacheAdministration.cs new file mode 100644 index 00000000..02b7f70f --- /dev/null +++ b/BITS/PeerCacheAdministration.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Vanara.Collections; +using Vanara.Extensions; +using Vanara.InteropServices; +using Vanara.PInvoke; +using static Vanara.PInvoke.BITS; + +namespace Vanara.IO; + +/// Use PeerCacheAdministration to manage the pool of peers from which you can download content. +public static class PeerCacheAdministration +{ + internal static readonly ComReleaser ciCacheAdmin = ComReleaserFactory.Create((IBitsPeerCacheAdministration)BackgroundCopyManager.IMgr); + + /// + /// Gets or sets the configuration flags that determine if the computer serves content to peers and can download content from peers. + /// + /// Flags that determine if the computer serves content to peers and can download content from peers. + public static PeerCaching ConfigurationFlags + { + get => (PeerCaching)ciCacheAdmin.Item.GetConfigurationFlags(); + set => ciCacheAdmin.Item.SetConfigurationFlags((BG_ENABLE_PEERCACHING)value); + } + + /// Gets or sets the maximum size of the cache. + /// Maximum size of the cache, as a percentage of available hard disk drive space. + public static uint MaximumCacheSize + { + get => ciCacheAdmin.Item.GetMaximumCacheSize(); + set => ciCacheAdmin.Item.SetMaximumCacheSize(value); + } + + /// Gets or sets the age by when files are removed from the cache. + /// Age. If the last time that the file was accessed is older than this age, BITS removes the file from the cache. + public static TimeSpan MaximumContentAge + { + get => TimeSpan.FromSeconds(ciCacheAdmin.Item.GetMaximumContentAge()); + set => ciCacheAdmin.Item.SetMaximumContentAge((uint)value.TotalSeconds); + } + + /// Gets a instance that you use to enumerate the peers that can serve content. + /// A instance that you use to enumerate the peers that can serve content. + public static CachePeers Peers { get; } = new CachePeers(); + + /// + /// Gets a instance that you use to enumerate the records in the cache. The enumeration is a snapshot of + /// the records in the cache. + /// + /// A instance that you use to enumerate the records in the cache. + public static PeerCacheRecords Records { get; } = new PeerCacheRecords(); + + /// Deletes all cache records and the file from the cache for the given URL. + /// + /// Null-terminated string that contains the URL of the file whose cache records and file you want to delete from the cache. + /// + public static void DeleteUrl(string url) => ciCacheAdmin.Item.DeleteUrl(url); + + /// Provides the ability to enumerate the list of peers that BITS has discovered. + public class CachePeers : IReadOnlyCollection + { + /// Gets the number of elements in the collection. + public int Count => EnumPeers().Count(); + + /// Removes all peers from the list of peers that can serve content. + public static void Clear() => ciCacheAdmin.Item.ClearPeers(); + + /// Returns an enumerator that iterates through the collection. + /// An enumerator that can be used to iterate through the collection. + public IEnumerator GetEnumerator() + { + ciCacheAdmin.Item.DiscoverPeers(); + return EnumPeers().GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private IEnumerable EnumPeers() => IEnumFromCom.Create(ciCacheAdmin.Item.EnumPeers()).Select(i => new CachePeer(i)); + } + + /// Provides the ability to enumerate the records of the cache. + public class PeerCacheRecords : IReadOnlyList + { + internal PeerCacheRecords() { } + + /// Gets the number of elements in the collection. + public int Count => EnumRecords().Count(); + + /// Gets the at the specified index. + /// The . + /// The index. + /// A instance of the cache record. + public PeerCacheRecord this[int index] => EnumRecords().ElementAt(index); + + /// Gets a record from the cache. + /// Identifier of the record to get from the cache. + /// A instance of the cache record. + public PeerCacheRecord this[Guid id] => new(ciCacheAdmin.Item.GetRecord(id)); + + /// Removes all the records and files from the cache. + public void Clear() => ciCacheAdmin.Item.ClearRecords(); + + /// Determines whether this collection contains the specified record. + /// The record. + /// if the specified item is contained in the collection; otherwise, . + public bool Contains(PeerCacheRecord item) => EnumRecords().Contains(item); + + /// Returns an enumerator that iterates through the collection. + /// An enumerator that can be used to iterate through the collection. + public IEnumerator GetEnumerator() => EnumRecords().GetEnumerator(); + + /// Searches for the specified record and returns the zero-based index of the first occurrence within the colection. + /// The record to locate in the collection. The value can be . + /// The zero-based index of the first occurrence of within the entire collection, if found; otherwise, -1. + public int IndexOf(PeerCacheRecord item) => EnumRecords().SelectMany((value, index) => value == item ? new[] { index } : Enumerable.Empty()).DefaultIfEmpty(-1).First(); + + /// Deletes a record and file from the cache. + /// The record to delete from the cache. + public bool Remove(PeerCacheRecord item) { try { ciCacheAdmin.Item.DeleteRecord(item.Id); return true; } catch { return false; } } + + /// Removes the element at the specified index of the collection. + /// The zero-based index of the element to remove. + public void RemoveAt(int index) => Remove(EnumRecords().ElementAt(index)); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private IEnumerable EnumRecords() => IEnumFromCom.Create(ciCacheAdmin.Item.EnumRecords()).Select(i => new PeerCacheRecord(i)); + } +} + +/// Provides information about a peer in the neighborhood. +public class CachePeer +{ + private readonly ComReleaser ciPeer; + + internal CachePeer(IBitsPeer peer) => ciPeer = ComReleaserFactory.Create(peer); + + private CachePeer() => throw new NotImplementedException(); + /// Determines whether the peer is authenticated. + /// if the peer is authenticated, otherwise, . + public bool IsAuthenticated => ciPeer.Item.IsAuthenticated(); + + /// Determines whether the peer is available (online) to serve content. + /// if the peer is available to serve content, otherwise, . + public bool IsAvailable => ciPeer.Item.IsAvailable(); + + /// Gets the server principal name that uniquely identifies the peer. + /// The server principal name of the peer. The principal name is of the form, server$.domain.suffix. + public string Name => ciPeer.Item.GetPeerName(); +} + +/// Provides information about a file in the BITS peer cache. +public class PeerCacheRecord +{ + private readonly ComReleaser ciRecord; + + internal PeerCacheRecord(IBitsPeerCacheRecord bitsPeerCacheRecord) => ciRecord = ComReleaserFactory.Create(bitsPeerCacheRecord); + + private PeerCacheRecord() => throw new NotImplementedException(); + /// Gets the date and time that the file was last modified on the server. + /// Date and time that the file was last modified on the server. + public DateTime FileModificationTime => ciRecord.Item.GetFileModificationTime().ToDateTime(); + + /// Gets the ranges of the file that are in the cache. + /// Array of structures that specify the ranges of the file that are in the cache. + public BackgroundCopyFileRange[] FileRanges => Array.ConvertAll(ciRecord.Item.GetFileRanges(), i => (BackgroundCopyFileRange)i); + + /// Gets the size of the file. + /// Size of the file, in bytes. + public ulong FileSize => ciRecord.Item.GetFileSize(); + + /// Gets the record identifier. + /// The identifier. + public Guid Id => ciRecord.Item.GetId(); + + /// Determines whether the file has been validated. + /// if file has been validated; otherwise . + public bool IsFileValidated => ciRecord.Item.IsFileValidated() == HRESULT.S_OK; + + /// Gets the date and time that the file was last accessed. + /// Date and time that the file was last accessed. + public DateTime LastAccessTime => ciRecord.Item.GetLastAccessTime().ToDateTime(); + + /// Gets the origin URL of the cached file. + /// String that contains the origin URL of the cached file. + public string OriginUrl => ciRecord.Item.GetOriginUrl(); +} \ No newline at end of file diff --git a/BITS/Vanara.BITS.csproj b/BITS/Vanara.BITS.csproj index 5d51d599..39827ae5 100644 --- a/BITS/Vanara.BITS.csproj +++ b/BITS/Vanara.BITS.csproj @@ -19,6 +19,7 @@ BackgroundCopyACLFlags, BackgroundCopyCost, BackgroundCopyErrorContext, Backgrou pkgreadme.md + Vanara.IO diff --git a/PInvoke/BITS/bits.cs b/PInvoke/BITS/bits.cs index 4275f0b2..3df71d4c 100644 --- a/PInvoke/BITS/bits.cs +++ b/PInvoke/BITS/bits.cs @@ -134,6 +134,7 @@ namespace Vanara.PInvoke } /// Flags that determine if the computer serves content to peers and can download content from peers. + [Flags] public enum BG_ENABLE_PEERCACHING { /// @@ -258,6 +259,7 @@ namespace Vanara.PInvoke /// /// Flags that determine if the files of the job can be cached and served to peers and if BITS can download content for the job from peers. /// + [Flags] public enum BG_JOB_ENABLE_PEERCACHING { /// @@ -2856,9 +2858,50 @@ namespace Vanara.PInvoke /// Sets flags that determine if the files of the job can be cached and served to peers and if the job can download content from peers. /// /// + /// /// Flags that determine if the files of the job can be cached and served to peers and if the job can download content from /// peers. The following flags can be set: + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_CLIENT 0x0001 + /// + /// The job can download content from peers. The job will not download from a peer unless both the client computer and the job + /// allow Background Intelligent Transfer Service (BITS) to download files from a peer. To enable the client computer to download + /// files from a peer, set the EnablePeerCaching group policy or call the IBitsPeerCacheAdministration::SetConfigurationFlags + /// method and set the BG_ENABLE_PEERCACHING_CLIENT flag. If one of the following conditions exists, BITS will stop the download + /// and reschedule the job to begin transferring from either a peer or the origin server, depending on the value for the job and + /// the cache:The download will then resume from where it left off before BITS stopped the job. BITS 4.0: This flag is deprecated. + /// + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_SERVER 0x0002 + /// + /// The files of the job can be cached and served to peers. BITS will not cache the files and serve them to peers unless both the + /// client computer and job allow BITS to cache and serve the files. To allow BITS to cache and serve the files on the client + /// computer, set the EnablePeerCaching group policy or call the IBitsPeerCacheAdministration::SetConfigurationFlags method and + /// set the BG_ENABLE_PEERCACHING_SERVER flag. BITS 4.0: This flag is deprecated. + /// + /// + /// + /// BG_JOB_DISABLE_BRANCH_CACHE 0x0004 + /// + /// BITS will not use Windows BranchCache for transfer jobs. This setting does not affect the use of Windows BranchCache by + /// applications other than BITS. + /// + /// + /// /// + /// + /// Setting these flags has meaning only if the peer caching has been enabled by either setting the EnablePeerCaching group + /// policy or calling the IBitsPeerCacheAdministration::SetConfigurationFlags. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/bits3_0/nf-bits3_0-ibackgroundcopyjob4-setpeercachingflags + // HRESULT SetPeerCachingFlags( [in] DWORD Flags ); void SetPeerCachingFlags(BG_JOB_ENABLE_PEERCACHING Flags); /// @@ -2866,9 +2909,31 @@ namespace Vanara.PInvoke /// the job from peers. /// /// + /// /// Flags that determine if the files of the job can be cached and served to peers and if BITS can download content for the job /// from peers. The following flags can be set: + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_CLIENT 0x0001 + /// The job can download content from peers. + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_SERVER 0x0002 + /// The files of the job can be cached and served to peers. + /// + /// /// + /// + /// BITS can download from peers only if peercaching is enabled both at the computer level and at the job level; this API affects + /// only the job level. For details, see IBackgroundCopyJob4::SetPeerCachingFlags. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/bits3_0/nf-bits3_0-ibackgroundcopyjob4-getpeercachingflags + // HRESULT GetPeerCachingFlags( [out] DWORD *pFlags ); BG_JOB_ENABLE_PEERCACHING GetPeerCachingFlags(); /// Gets the integrity level of the token of the owner that created or took ownership of the job. @@ -3291,9 +3356,48 @@ namespace Vanara.PInvoke /// Sets flags that determine if the files of the job can be cached and served to peers and if the job can download content from peers. /// /// + /// /// Flags that determine if the files of the job can be cached and served to peers and if the job can download content from /// peers. The following flags can be set: + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_CLIENT 0x0001 + /// + /// The job can download content from peers. The job will not download from a peer unless both the client computer and the job + /// allow Background Intelligent Transfer Service (BITS) to download files from a peer. To enable the client computer to download + /// files from a peer, set the EnablePeerCaching group policy or call the IBitsPeerCacheAdministration::SetConfigurationFlags + /// method and set the BG_ENABLE_PEERCACHING_CLIENT flag. If one of the following conditions exists, BITS will stop the download + /// and reschedule the job to begin transferring from either a peer or the origin server, depending on the value for the job and + /// the cache:The download will then resume from where it left off before BITS stopped the job. BITS 4.0: This flag is deprecated. + /// + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_SERVER 0x0002 + /// + /// The files of the job can be cached and served to peers. BITS will not cache the files and serve them to peers unless both the + /// client computer and job allow BITS to cache and serve the files. To allow BITS to cache and serve the files on the client + /// computer, set the EnablePeerCaching group policy or call the IBitsPeerCacheAdministration::SetConfigurationFlags method and + /// set the BG_ENABLE_PEERCACHING_SERVER flag. BITS 4.0: This flag is deprecated. + /// + /// + /// + /// BG_JOB_DISABLE_BRANCH_CACHE 0x0004 + /// + /// BITS will not use Windows BranchCache for transfer jobs. This setting does not affect the use of Windows BranchCache by + /// applications other than BITS. + /// + /// + /// /// + /// + /// Setting these flags has meaning only if the peer caching has been enabled by either setting the EnablePeerCaching group + /// policy or calling the IBitsPeerCacheAdministration::SetConfigurationFlags. + /// new void SetPeerCachingFlags(BG_JOB_ENABLE_PEERCACHING Flags); /// @@ -3301,9 +3405,29 @@ namespace Vanara.PInvoke /// the job from peers. /// /// + /// /// Flags that determine if the files of the job can be cached and served to peers and if BITS can download content for the job /// from peers. The following flags can be set: + /// + /// + /// + /// Value + /// Meaning + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_CLIENT 0x0001 + /// The job can download content from peers. + /// + /// + /// BG_JOB_ENABLE_PEERCACHING_SERVER 0x0002 + /// The files of the job can be cached and served to peers. + /// + /// /// + /// + /// BITS can download from peers only if peercaching is enabled both at the computer level and at the job level; this API affects + /// only the job level. For details, see IBackgroundCopyJob4::SetPeerCachingFlags. + /// new BG_JOB_ENABLE_PEERCACHING GetPeerCachingFlags(); /// Gets the integrity level of the token of the owner that created or took ownership of the job. @@ -4495,7 +4619,7 @@ namespace Vanara.PInvoke // https://msdn.microsoft.com/en-us/library/windows/desktop/aa964302(v=vs.85).aspx [PInvokeData("Bits3_0.h", MSDNShortId = "aa964302")] [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("659CDEA4-489E-11D9-A9CD-000D56965251")] - public interface IEnumBitsPeerCacheRecords + public interface IEnumBitsPeerCacheRecords : Vanara.Collections.ICOMEnum { /// /// Retrieves a specified number of items in the enumeration sequence. If there are fewer than the requested number of elements @@ -4544,7 +4668,7 @@ namespace Vanara.PInvoke // https://msdn.microsoft.com/en-us/library/windows/desktop/aa964308(v=vs.85).aspx [PInvokeData("Bits3_0.h", MSDNShortId = "aa964308")] [ComImport, Guid("659CDEA5-489E-11D9-A9CD-000D56965251"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IEnumBitsPeers + public interface IEnumBitsPeers : Vanara.Collections.ICOMEnum { /// /// Retrieves a specified number of items in the enumeration sequence. If there are fewer than the requested number of elements