From 1dd14e66a191b4d58a99c6e7f2c476ce7092d7e4 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Thu, 5 Dec 2024 13:43:58 +0000 Subject: [PATCH 1/8] adding WLI auth support --- Directory.Packages.props | 1 + libs/host/Configuration/Options.cs | 25 ++++++++++++--- libs/host/defaults.conf | 6 ++++ .../AzureStorageNamedDeviceFactory.cs | 12 +++++++ .../AzureStorageDevice/BlobUtilsV12.cs | 32 +++++++++++++++++++ ...savorite.devices.AzureStorageDevice.csproj | 1 + 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a346e27eca..1c8d9f8c2a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,5 +27,6 @@ + \ No newline at end of file diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs index 1bae3a7d84..b26ef32c2c 100644 --- a/libs/host/Configuration/Options.cs +++ b/libs/host/Configuration/Options.cs @@ -315,6 +315,12 @@ internal sealed class Options [Option("use-azure-storage", Required = false, HelpText = "Use Azure Page Blobs for storage instead of local storage.")] public bool? UseAzureStorage { get; set; } + [Option("client-id", Required = false, HelpText = "The client id to use when establishing connection to Azure Blobs Storage.")] + public string AzureStorageClientId { get; set; } + + [Option("storage-account-uri", Required = false, HelpText = "The storage account uri to use when establishing connection to Azure Blobs Storage.")] + public string AzureStorageAccountUri { get; set; } + [Option("storage-string", Required = false, HelpText = "The connection string to use when establishing connection to Azure Blobs Storage.")] public string AzureStorageConnectionString { get; set; } @@ -510,9 +516,21 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) var useAzureStorage = UseAzureStorage.GetValueOrDefault(); var enableStorageTier = EnableStorageTier.GetValueOrDefault(); var enableRevivification = EnableRevivification.GetValueOrDefault(); + Uri azureStorageUri = null; + + if (useAzureStorage && string.IsNullOrEmpty(AzureStorageConnectionString) && string.IsNullOrEmpty(AzureStorageAccountUri)) + throw new Exception("Cannot enable use-azure-storage without supplying storage-string or storage-account-uri."); - if (useAzureStorage && string.IsNullOrEmpty(AzureStorageConnectionString)) - throw new Exception("Cannot enable use-azure-storage without supplying storage-string."); + if (useAzureStorage) + { + if (string.IsNullOrEmpty(AzureStorageConnectionString)){ + azureStorageUri= new Uri(AzureStorageAccountUri); + logger?.LogInformation("Azure Storage URI: {azureStorageUri}", azureStorageUri); + } + } + Func azureFactoryCreator = string.IsNullOrEmpty(AzureStorageConnectionString) + ? () => new AzureStorageNamedDeviceFactory(azureStorageUri,AzureStorageClientId, logger) + : () => new AzureStorageNamedDeviceFactory(AzureStorageConnectionString, logger); var logDir = LogDir; if (!useAzureStorage && enableStorageTier) logDir = new DirectoryInfo(string.IsNullOrEmpty(logDir) ? "." : logDir).FullName; @@ -633,8 +651,7 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) QuietMode = QuietMode.GetValueOrDefault(), ThreadPoolMinThreads = ThreadPoolMinThreads, ThreadPoolMaxThreads = ThreadPoolMaxThreads, - DeviceFactoryCreator = useAzureStorage - ? () => new AzureStorageNamedDeviceFactory(AzureStorageConnectionString, logger) + DeviceFactoryCreator = useAzureStorage ? azureFactoryCreator : () => new LocalStorageNamedDeviceFactory(useNativeDeviceLinux: UseNativeDeviceLinux.GetValueOrDefault(), logger: logger), CheckpointThrottleFlushDelayMs = CheckpointThrottleFlushDelayMs, EnableScatterGatherGet = EnableScatterGatherGet.GetValueOrDefault(), diff --git a/libs/host/defaults.conf b/libs/host/defaults.conf index 27e700c966..c9a2cdb938 100644 --- a/libs/host/defaults.conf +++ b/libs/host/defaults.conf @@ -236,6 +236,12 @@ /* The connection string to use when establishing connection to Azure Blobs Storage. */ "AzureStorageConnectionString" : null, + /* The clientid required to connect to storage account. */ + "AzureStorageClientId": null, + + /* The Storage acount URI required to connect to storage account. */ + "AzureStorageAccountUri": null, + /* Whether and by how much should we throttle the disk IO for checkpoints: -1 - disable throttling; >= 0 - run checkpoint flush in separate task, sleep for specified time after each WriteAsync */ "CheckpointThrottleFlushDelayMs" : 0, diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs index 2bf672f308..f65c3de9d5 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -29,6 +30,17 @@ public AzureStorageNamedDeviceFactory(string connectionString, ILogger logger = { } + /// + /// Create instance of factory of Azure devices + /// + /// + /// + /// + public AzureStorageNamedDeviceFactory( Uri serviceUri, string managedIdentityClientId,ILogger logger = null) + : this(BlobUtilsV12.GetServiceClients(serviceUri,managedIdentityClientId), logger) + { + } + /// /// Create instance of factory for Azure devices /// diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs index eb04700bc5..176bf9f9f6 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs @@ -9,6 +9,7 @@ namespace Tsavorite.devices using System.Threading.Tasks; using Azure.Core; using Azure.Core.Pipeline; + using Azure.Identity; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Specialized; @@ -62,6 +63,37 @@ internal static ServiceClients GetServiceClients(string connectionString) }; } + internal static ServiceClients GetServiceClients(Uri serviceUri,string userAssignedClientId) + { + var aggressiveOptions = new BlobClientOptions(); + aggressiveOptions.Retry.MaxRetries = 0; + aggressiveOptions.Retry.NetworkTimeout = TimeSpan.FromSeconds(3); + aggressiveOptions.AddPolicy(new ServerTimeoutPolicy(2), HttpPipelinePosition.PerCall); + + var defaultOptions = new BlobClientOptions(); + defaultOptions.Retry.MaxRetries = 0; + defaultOptions.Retry.NetworkTimeout = TimeSpan.FromSeconds(16); + defaultOptions.AddPolicy(new ServerTimeoutPolicy(15), HttpPipelinePosition.PerCall); + + var withRetriesOptions = new BlobClientOptions(); + withRetriesOptions.Retry.MaxRetries = 10; + withRetriesOptions.Retry.Mode = RetryMode.Exponential; + withRetriesOptions.Retry.Delay = TimeSpan.FromSeconds(1); + withRetriesOptions.Retry.MaxDelay = TimeSpan.FromSeconds(30); + + var tokenCredential = new ChainedTokenCredential( + new WorkloadIdentityCredential(), + new ManagedIdentityCredential(clientId: userAssignedClientId) + ); + + return new ServiceClients() + { + Default = new BlobServiceClient(serviceUri,tokenCredential, defaultOptions), + Aggressive = new BlobServiceClient(serviceUri,tokenCredential, aggressiveOptions), + WithRetries = new BlobServiceClient(serviceUri,tokenCredential, withRetriesOptions), + }; + } + public struct ContainerClients { public BlobContainerClient Default; diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj index 6b9cab0775..c5a456e561 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj @@ -12,6 +12,7 @@ + From 9d8d5e541784b1a184db93b29284e03297228df9 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 11 Feb 2025 15:14:37 +0000 Subject: [PATCH 2/8] Updating Azure device to create a file if it doesn't exist when reading --- libs/host/Configuration/Options.cs | 3 +- .../AzureStorageDevice/AzureStorageDevice.cs | 77 +++++++++++++------ 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs index cde1611685..ef75165f96 100644 --- a/libs/host/Configuration/Options.cs +++ b/libs/host/Configuration/Options.cs @@ -355,7 +355,7 @@ internal sealed class Options [Option("use-azure-storage", Required = false, HelpText = "Use Azure Page Blobs for storage instead of local storage.")] public bool? UseAzureStorage { get; set; } - [Option("client-id", Required = false, HelpText = "The client id to use when establishing connection to Azure Blobs Storage.")] + [Option("azure-storage-client-id", Required = false, HelpText = "The client id to use when establishing connection to Azure Blobs Storage.")] public string AzureStorageClientId { get; set; } [Option("storage-account-uri", Required = false, HelpText = "The storage account uri to use when establishing connection to Azure Blobs Storage.")] @@ -573,7 +573,6 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) { if (string.IsNullOrEmpty(AzureStorageConnectionString)){ azureStorageUri= new Uri(AzureStorageAccountUri); - logger?.LogInformation("Azure Storage URI: {azureStorageUri}", azureStorageUri); } } Func azureFactoryCreator = string.IsNullOrEmpty(AzureStorageConnectionString) diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs index 0413245f9c..fbeaa00fcb 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs @@ -135,7 +135,7 @@ internal AzureStorageDevice(string blobName, BlobUtilsV12.BlobDirectory pageBlob this.blobName = blobName; if (blobManager == null) localBlobManager = true; - BlobManager = blobManager ?? new BlobManager(logger, logger, LogLevel.Information, null, underLease, pageBlobDirectory, blobName); + BlobManager = blobManager ?? new BlobManager(logger, logger, LogLevel.Trace, null, underLease, pageBlobDirectory, blobName); StorageErrorHandler = BlobManager.StorageErrorHandler; StorageErrorHandler.Token.Register(CancelAllRequests); @@ -440,29 +440,56 @@ public override unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr // Lazily cache the blob entry for the segment being read if (!blobs.TryGetValue(segmentId, out BlobEntry blobEntry)) { - var blobClients = pageBlobDirectory.GetPageBlobClient(GetSegmentBlobName(segmentId)); - var entry = new BlobEntry(blobClients, blobClients.Default.GetProperties().Value.ETag, this); - blobs.TryAdd(segmentId, entry); + BlobEntry entry = new(this); + if (blobs.TryAdd(segmentId, entry)) + { + var pageBlob = pageBlobDirectory.GetPageBlobClient(GetSegmentBlobName(segmentId)); + + // If segment size is -1 we use a default + var size = segmentSize == -1 ? MAX_PAGEBLOB_SIZE : segmentSize; + + // If no blob exists for the segment, we must first create the segment asynchronouly. (Create call takes ~70 ms by measurement) + // After creation is done, we can call read. + _ = entry.CreateAsync(size, pageBlob); + } + // Otherwise, some other thread beat us to it. Okay to use their blobs. blobEntry = blobs[segmentId]; } - ReadFromBlobUnsafeAsync(blobEntry.PageBlob, (long)sourceAddress, (long)destinationAddress, readLength, id) - .ContinueWith((Task t) => - { - if (pendingReadWriteOperations.TryRemove(id, out ReadWriteRequestInfo request)) - { - if (t.IsFaulted) - { - BlobManager?.StorageTracer?.TsavoriteStorageProgress($"StorageOpReturned AzureStorageDevice.ReadAsync id={id} (Failure)"); - request.Callback(uint.MaxValue, request.NumBytes, request.Context); - } - else - { - BlobManager?.StorageTracer?.TsavoriteStorageProgress($"StorageOpReturned AzureStorageDevice.ReadAsync id={id}"); - request.Callback(0, request.NumBytes, request.Context); - } - } - }, TaskContinuationOptions.ExecuteSynchronously); + TryReadAsync(blobEntry, (long)sourceAddress, (long)destinationAddress, readLength, id); + } + + void TryReadAsync( BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) + { + // If pageBlob is null, it means the blob has not been created yet. We should wait for it to be created. + if (blobEntry.PageBlob.Default==null + && blobEntry.TryQueueAction(() => ReadToBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id))) + { + return; + } + // Otherwise, we can proceed with the read. + ReadToBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id); + } + + unsafe void ReadToBlobAsync(BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) + { + ReadFromBlobUnsafeAsync(blobEntry, sourceAddress, destinationAddress, readLength, id) + .ContinueWith((Task t) => + { + if (pendingReadWriteOperations.TryRemove(id, out ReadWriteRequestInfo request)) + { + if (t.IsFaulted) + { + BlobManager?.StorageTracer?.TsavoriteStorageProgress($"StorageOpReturned AzureStorageDevice.ReadAsync id={id} (Failure)"); + request.Callback(uint.MaxValue, request.NumBytes, request.Context); + } + else + { + BlobManager?.StorageTracer?.TsavoriteStorageProgress($"StorageOpReturned AzureStorageDevice.ReadAsync id={id} for blob={blobEntry.ETag}"); + request.Callback(0, request.NumBytes, request.Context); + } + } + }, TaskContinuationOptions.ExecuteSynchronously); } /// @@ -557,12 +584,12 @@ await BlobManager.PerformWithRetriesAsync( } } - unsafe Task ReadFromBlobUnsafeAsync(BlobUtilsV12.PageBlobClients blob, long sourceAddress, long destinationAddress, uint readLength, long id) + unsafe Task ReadFromBlobUnsafeAsync(BlobEntry blob, long sourceAddress, long destinationAddress, uint readLength, long id) { return ReadFromBlobAsync(new UnmanagedMemoryStream((byte*)destinationAddress, readLength, readLength, FileAccess.Write), blob, sourceAddress, readLength, id); } - async Task ReadFromBlobAsync(UnmanagedMemoryStream stream, BlobUtilsV12.PageBlobClients blob, long sourceAddress, uint readLength, long id) + async Task ReadFromBlobAsync(UnmanagedMemoryStream stream, BlobEntry blob, long sourceAddress, uint readLength, long id) { using (stream) { @@ -577,7 +604,7 @@ await BlobManager.PerformWithRetriesAsync( "PageBlobClient.DownloadStreamingAsync", "ReadFromDevice", $"id={id} readLength={length} sourceAddress={sourceAddress + offset}", - blob.Default.Name, + blob.PageBlob.Default.Name, 1000 + (int)length / 1000, true, async (numAttempts) => @@ -589,7 +616,7 @@ await BlobManager.PerformWithRetriesAsync( if (length > 0) { - var client = (numAttempts > 1 || length == MAX_DOWNLOAD_SIZE) ? blob.Default : blob.Aggressive; + var client = (numAttempts > 1 || length == MAX_DOWNLOAD_SIZE) ? blob.PageBlob.Default : blob.PageBlob.Aggressive; var response = await client.DownloadStreamingAsync( range: new Azure.HttpRange(sourceAddress + offset, length), From c3c5b734a26fe4fae85149d1033c5e66b2f15c7f Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 18 Feb 2025 06:42:13 +0000 Subject: [PATCH 3/8] reverting log level --- .../cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs index fbeaa00fcb..303e8becba 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs @@ -135,7 +135,7 @@ internal AzureStorageDevice(string blobName, BlobUtilsV12.BlobDirectory pageBlob this.blobName = blobName; if (blobManager == null) localBlobManager = true; - BlobManager = blobManager ?? new BlobManager(logger, logger, LogLevel.Trace, null, underLease, pageBlobDirectory, blobName); + BlobManager = blobManager ?? new BlobManager(logger, logger, LogLevel.Information, null, underLease, pageBlobDirectory, blobName); StorageErrorHandler = BlobManager.StorageErrorHandler; StorageErrorHandler.Token.Register(CancelAllRequests); From 7ef7782ff959150cc679fec58962bd76dac4a6f9 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 18 Feb 2025 08:11:25 +0000 Subject: [PATCH 4/8] reverting managedIdentity changes --- libs/host/Configuration/Options.cs | 27 +++------------- libs/host/defaults.conf | 6 ---- .../AzureStorageNamedDeviceFactory.cs | 11 ------- .../AzureStorageDevice/BlobUtilsV12.cs | 32 ------------------- ...savorite.devices.AzureStorageDevice.csproj | 1 - 5 files changed, 5 insertions(+), 72 deletions(-) diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs index f3ffe4645d..40c1b984a0 100644 --- a/libs/host/Configuration/Options.cs +++ b/libs/host/Configuration/Options.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; @@ -369,12 +369,6 @@ internal sealed class Options [Option("use-azure-storage", Required = false, HelpText = "Use Azure Page Blobs for storage instead of local storage.")] public bool? UseAzureStorage { get; set; } - [Option("azure-storage-client-id", Required = false, HelpText = "The client id to use when establishing connection to Azure Blobs Storage.")] - public string AzureStorageClientId { get; set; } - - [Option("storage-account-uri", Required = false, HelpText = "The storage account uri to use when establishing connection to Azure Blobs Storage.")] - public string AzureStorageAccountUri { get; set; } - [Option("storage-string", Required = false, HelpText = "The connection string to use when establishing connection to Azure Blobs Storage.")] public string AzureStorageConnectionString { get; set; } @@ -609,20 +603,8 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) var useAzureStorage = UseAzureStorage.GetValueOrDefault(); var enableStorageTier = EnableStorageTier.GetValueOrDefault(); var enableRevivification = EnableRevivification.GetValueOrDefault(); - Uri azureStorageUri = null; - - if (useAzureStorage && string.IsNullOrEmpty(AzureStorageConnectionString) && string.IsNullOrEmpty(AzureStorageAccountUri)) - throw new Exception("Cannot enable use-azure-storage without supplying storage-string or storage-account-uri."); - - if (useAzureStorage) - { - if (string.IsNullOrEmpty(AzureStorageConnectionString)){ - azureStorageUri= new Uri(AzureStorageAccountUri); - } - } - Func azureFactoryCreator = string.IsNullOrEmpty(AzureStorageConnectionString) - ? () => new AzureStorageNamedDeviceFactory(azureStorageUri,AzureStorageClientId, logger) - : () => new AzureStorageNamedDeviceFactory(AzureStorageConnectionString, logger); + if (useAzureStorage && string.IsNullOrEmpty(AzureStorageConnectionString)) + throw new Exception("Cannot enable use-azure-storage without supplying storage-string."); var logDir = LogDir; if (!useAzureStorage && enableStorageTier) logDir = new DirectoryInfo(string.IsNullOrEmpty(logDir) ? "." : logDir).FullName; @@ -781,7 +763,8 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) ThreadPoolMinIOCompletionThreads = ThreadPoolMinIOCompletionThreads, ThreadPoolMaxIOCompletionThreads = ThreadPoolMaxIOCompletionThreads, NetworkConnectionLimit = NetworkConnectionLimit, - DeviceFactoryCreator = useAzureStorage ? azureFactoryCreator + DeviceFactoryCreator = useAzureStorage + ? () => new AzureStorageNamedDeviceFactory(AzureStorageConnectionString, logger) : () => new LocalStorageNamedDeviceFactory(useNativeDeviceLinux: UseNativeDeviceLinux.GetValueOrDefault(), logger: logger), CheckpointThrottleFlushDelayMs = CheckpointThrottleFlushDelayMs, EnableScatterGatherGet = EnableScatterGatherGet.GetValueOrDefault(), diff --git a/libs/host/defaults.conf b/libs/host/defaults.conf index 4269cbae62..16b721acb5 100644 --- a/libs/host/defaults.conf +++ b/libs/host/defaults.conf @@ -275,12 +275,6 @@ /* The connection string to use when establishing connection to Azure Blobs Storage. */ "AzureStorageConnectionString" : null, - /* The clientid required to connect to storage account. */ - "AzureStorageClientId": null, - - /* The Storage acount URI required to connect to storage account. */ - "AzureStorageAccountUri": null, - /* Whether and by how much should we throttle the disk IO for checkpoints: -1 - disable throttling; >= 0 - run checkpoint flush in separate task, sleep for specified time after each WriteAsync */ "CheckpointThrottleFlushDelayMs" : 0, diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs index f65c3de9d5..8f7bf665d4 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs @@ -30,17 +30,6 @@ public AzureStorageNamedDeviceFactory(string connectionString, ILogger logger = { } - /// - /// Create instance of factory of Azure devices - /// - /// - /// - /// - public AzureStorageNamedDeviceFactory( Uri serviceUri, string managedIdentityClientId,ILogger logger = null) - : this(BlobUtilsV12.GetServiceClients(serviceUri,managedIdentityClientId), logger) - { - } - /// /// Create instance of factory for Azure devices /// diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs index 176bf9f9f6..eb04700bc5 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/BlobUtilsV12.cs @@ -9,7 +9,6 @@ namespace Tsavorite.devices using System.Threading.Tasks; using Azure.Core; using Azure.Core.Pipeline; - using Azure.Identity; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Specialized; @@ -63,37 +62,6 @@ internal static ServiceClients GetServiceClients(string connectionString) }; } - internal static ServiceClients GetServiceClients(Uri serviceUri,string userAssignedClientId) - { - var aggressiveOptions = new BlobClientOptions(); - aggressiveOptions.Retry.MaxRetries = 0; - aggressiveOptions.Retry.NetworkTimeout = TimeSpan.FromSeconds(3); - aggressiveOptions.AddPolicy(new ServerTimeoutPolicy(2), HttpPipelinePosition.PerCall); - - var defaultOptions = new BlobClientOptions(); - defaultOptions.Retry.MaxRetries = 0; - defaultOptions.Retry.NetworkTimeout = TimeSpan.FromSeconds(16); - defaultOptions.AddPolicy(new ServerTimeoutPolicy(15), HttpPipelinePosition.PerCall); - - var withRetriesOptions = new BlobClientOptions(); - withRetriesOptions.Retry.MaxRetries = 10; - withRetriesOptions.Retry.Mode = RetryMode.Exponential; - withRetriesOptions.Retry.Delay = TimeSpan.FromSeconds(1); - withRetriesOptions.Retry.MaxDelay = TimeSpan.FromSeconds(30); - - var tokenCredential = new ChainedTokenCredential( - new WorkloadIdentityCredential(), - new ManagedIdentityCredential(clientId: userAssignedClientId) - ); - - return new ServiceClients() - { - Default = new BlobServiceClient(serviceUri,tokenCredential, defaultOptions), - Aggressive = new BlobServiceClient(serviceUri,tokenCredential, aggressiveOptions), - WithRetries = new BlobServiceClient(serviceUri,tokenCredential, withRetriesOptions), - }; - } - public struct ContainerClients { public BlobContainerClient Default; diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj index c5a456e561..6b9cab0775 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/Tsavorite.devices.AzureStorageDevice.csproj @@ -12,7 +12,6 @@ - From e20c65d7bcc9abd39c99861b1fc526351e09b36b Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 18 Feb 2025 08:15:22 +0000 Subject: [PATCH 5/8] removing azure identity pkg reference --- Directory.Packages.props | 1 - libs/host/Configuration/Options.cs | 1 + .../devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c62cb73788..0719a40ed8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,6 +27,5 @@ - \ No newline at end of file diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs index 40c1b984a0..5d53915df6 100644 --- a/libs/host/Configuration/Options.cs +++ b/libs/host/Configuration/Options.cs @@ -603,6 +603,7 @@ public GarnetServerOptions GetServerOptions(ILogger logger = null) var useAzureStorage = UseAzureStorage.GetValueOrDefault(); var enableStorageTier = EnableStorageTier.GetValueOrDefault(); var enableRevivification = EnableRevivification.GetValueOrDefault(); + if (useAzureStorage && string.IsNullOrEmpty(AzureStorageConnectionString)) throw new Exception("Cannot enable use-azure-storage without supplying storage-string."); diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs index 8f7bf665d4..2bf672f308 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageNamedDeviceFactory.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; From c344f1145ae930c239dbc3179068ff5511186ac2 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 18 Feb 2025 08:26:31 +0000 Subject: [PATCH 6/8] whitespace removed --- libs/host/Configuration/Options.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/host/Configuration/Options.cs b/libs/host/Configuration/Options.cs index 5d53915df6..41716c4d72 100644 --- a/libs/host/Configuration/Options.cs +++ b/libs/host/Configuration/Options.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; From 58b3d2a71c22473412b68dd9a5d399a5ddf0cfa0 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Tue, 18 Feb 2025 10:30:19 +0000 Subject: [PATCH 7/8] formatting whitespace bug --- .../cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs index 303e8becba..cc1bccba39 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs @@ -459,10 +459,10 @@ public override unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr TryReadAsync(blobEntry, (long)sourceAddress, (long)destinationAddress, readLength, id); } - void TryReadAsync( BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) + void TryReadAsync(BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) { // If pageBlob is null, it means the blob has not been created yet. We should wait for it to be created. - if (blobEntry.PageBlob.Default==null + if (blobEntry.PageBlob.Default == null && blobEntry.TryQueueAction(() => ReadToBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id))) { return; From 909b371bdce5cfdf37457d9d5846c38380603088 Mon Sep 17 00:00:00 2001 From: Priyanjali Gupta Date: Fri, 7 Mar 2025 11:42:44 +0000 Subject: [PATCH 8/8] renaming function --- .../cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs index cc1bccba39..9825a09248 100644 --- a/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs +++ b/libs/storage/Tsavorite/cs/src/devices/AzureStorageDevice/AzureStorageDevice.cs @@ -463,15 +463,15 @@ void TryReadAsync(BlobEntry blobEntry, long sourceAddress, long destinationAddre { // If pageBlob is null, it means the blob has not been created yet. We should wait for it to be created. if (blobEntry.PageBlob.Default == null - && blobEntry.TryQueueAction(() => ReadToBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id))) + && blobEntry.TryQueueAction(() => ReadFromBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id))) { return; } // Otherwise, we can proceed with the read. - ReadToBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id); + ReadFromBlobAsync(blobEntry, sourceAddress, destinationAddress, readLength, id); } - unsafe void ReadToBlobAsync(BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) + unsafe void ReadFromBlobAsync(BlobEntry blobEntry, long sourceAddress, long destinationAddress, uint readLength, long id) { ReadFromBlobUnsafeAsync(blobEntry, sourceAddress, destinationAddress, readLength, id) .ContinueWith((Task t) =>