From c96c40a8e25aec39e12e47bc94d91fbc4ca937de Mon Sep 17 00:00:00 2001 From: Dmitriy Kirakosyan Date: Fri, 13 Nov 2020 18:59:05 +0300 Subject: [PATCH 01/52] Add SetMaxStorageSizeAsync method signature --- .../AppCenter.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 9b215586d..7001b6978 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -255,6 +255,20 @@ public static void SetWrapperSdk(WrapperSdk wrapperSdk) DeviceInformationHelper.SetWrapperSdk(wrapperSdk); } + /// + /// Set the maximum size of the internal storage. This method must be called before App Center is started. This method is only intended for + /// applications. + /// + /// + /// This only sets the maximum size of the database, but App Center modules might store additional data. + /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + /// + /// Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). Values below 20,480 bytes (20 KiB) will be ignored. + /// true if changing the size was successful. + public static async Task SetMaxStorageSizeAsync(long sizeInBytes) + { + } + #endregion #region instance From 1295a6db47d858cb65857c29e7c7c0195d0767db Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Mon, 16 Nov 2020 10:31:41 +0300 Subject: [PATCH 02/52] Set max storage size method --- .../Microsoft.AppCenter.Shared/AppCenter.cs | 18 +++++ .../AppCenter.cs | 19 ++--- .../Channel/ChannelGroup.cs | 6 ++ .../Channel/IChannelGroup.cs | 2 + .../Storage/IStorage.cs | 14 ++++ .../Storage/IStorageAdapter.cs | 14 ++++ .../Storage/Storage.cs | 28 +++++++ .../Storage/StorageAdapter.cs | 81 ++++++++++++++++++- .../Microsoft.AppCenter/AppCenter.cs | 5 ++ 9 files changed, 172 insertions(+), 15 deletions(-) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs index 79705bc59..ed6360b71 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs @@ -198,6 +198,24 @@ public static void SetCustomProperties(CustomProperties customProperties) PlatformSetCustomProperties(customProperties); } + /// + /// Set the maximum size of the internal storage. + /// This method must be called before App Center is started. This method is only intended for applications. + /// + /// + /// This only sets the maximum size of the database, but App Center modules might store additional data. + /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + /// + /// + /// Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). + /// Values below 20,480 bytes (20 KiB) will be ignored. + /// + /// true if changing the size was successful. + public static Task SetMaxStorageSizeAsync(long sizeInBytes = 1024 * 1024 * 10) + { + return PlatformSetMaxStorageSizeAsync(sizeInBytes); + } + internal static void UnsetInstance() { PlatformUnsetInstance(); diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 7001b6978..0ba1b95ac 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -246,6 +246,11 @@ static void PlatformStart(string appSecret, params Type[] services) } } + static Task PlatformSetMaxStorageSizeAsync(long sizeInBytes) + { + return Instance._channelGroup?.SetMaxStorageSizeAsync(sizeInBytes); + } + /// /// A wrapper SDK can use this method to pass extra information to device properties. /// @@ -255,20 +260,6 @@ public static void SetWrapperSdk(WrapperSdk wrapperSdk) DeviceInformationHelper.SetWrapperSdk(wrapperSdk); } - /// - /// Set the maximum size of the internal storage. This method must be called before App Center is started. This method is only intended for - /// applications. - /// - /// - /// This only sets the maximum size of the database, but App Center modules might store additional data. - /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). - /// - /// Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). Values below 20,480 bytes (20 KiB) will be ignored. - /// true if changing the size was successful. - public static async Task SetMaxStorageSizeAsync(long sizeInBytes) - { - } - #endregion #region instance diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/ChannelGroup.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/ChannelGroup.cs index 55ab3c44a..ef57da69d 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/ChannelGroup.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/ChannelGroup.cs @@ -114,6 +114,12 @@ public void SetEnabled(bool enabled) } } + public Task SetMaxStorageSizeAsync(long sizeInBytes) + { + ThrowIfDisposed(); + return _storage.SetMaxStorageSizeAsync(sizeInBytes); + } + public Task WaitStorageOperationsAsync() { ThrowIfDisposed(); diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/IChannelGroup.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/IChannelGroup.cs index aae51ee15..c6dbea339 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/IChannelGroup.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Channel/IChannelGroup.cs @@ -37,5 +37,7 @@ public interface IChannelGroup : IChannel /// Waits for any running storage operations to complete. /// Task WaitStorageOperationsAsync(); + + Task SetMaxStorageSizeAsync(long sizeInBytes); } } diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorage.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorage.cs index 853f0aba9..7a648c461 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorage.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorage.cs @@ -74,5 +74,19 @@ public interface IStorage : IDisposable /// The maximum amount of time to wait for remaining tasks /// True if remaining tasks completed in time; false otherwise Task ShutdownAsync(TimeSpan timeout); + + /// + /// Set the maximum size of the storage. + /// + /// + /// This only sets the maximum size of the database, but App Center modules might store additional data. + /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + /// + /// + /// Maximum size of the storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). + /// Values below 20,480 bytes (20 KiB) will be ignored. + /// + /// true if changing the size was successful. + Task SetMaxStorageSizeAsync(long sizeInBytes); } } diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorageAdapter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorageAdapter.cs index 983ff3d1e..2b149a73d 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorageAdapter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/IStorageAdapter.cs @@ -61,5 +61,19 @@ public interface IStorageAdapter : IDisposable /// Name of column to match value by. /// Array of values to match in a query. void Delete(string tableName, string columnName, params object[] values); + + /// + /// Set the maximum size of the storage. + /// + /// + /// This only sets the maximum size of the database, but App Center modules might store additional data. + /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + /// + /// + /// Maximum size of the storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). + /// Values below 20,480 bytes (20 KiB) will be ignored. + /// + /// true if changing the size was successful. + bool SetMaxStorageSize(long sizeInBytes); } } diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/Storage.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/Storage.cs index 111dfe9bb..d668c0939 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/Storage.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/Storage.cs @@ -255,6 +255,34 @@ public Task GetLogsAsync(string channelName, int limit, List logs) }); } + /// + /// Set the maximum size of the storage. + /// + /// + /// This only sets the maximum size of the database, but App Center modules might store additional data. + /// The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB). + /// + /// + /// Maximum size of the storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size (default is 4096 bytes). + /// Values below 20,480 bytes (20 KiB) will be ignored. + /// + /// true if changing the size was successful. + public Task SetMaxStorageSizeAsync(long sizeInBytes) + { + return AddTaskToQueue(() => + { + try + { + AppCenterLog.Debug(AppCenterLog.LogTag, $"Set max storage size."); + return _storageAdapter.SetMaxStorageSize(sizeInBytes); + } + catch (KeyNotFoundException e) + { + throw new StorageException(e); + } + }); + } + private void ProcessLogIds(string channelName, string batchId, IEnumerable> idPairs) { var ids = new List(); diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs index 90597b87c..4ecc07022 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs @@ -95,7 +95,7 @@ private object GetColumnValue(sqlite3_stmt stmt, int index) return null; } - private void ExecuteNonSelectionSqlQuery(string query, IList args = null) + private int ExecuteNonSelectionSqlQuery(string query, IList args = null) { var db = _db ?? throw new StorageException("The database wasn't initialized."); var result = raw.sqlite3_prepare_v2(db, query, out var stmt); @@ -120,6 +120,8 @@ private void ExecuteNonSelectionSqlQuery(string query, IList args = null AppCenterLog.Error(AppCenterLog.LogTag, $"Failed to finalize statement, result={result}"); } } + + return result; } private List ExecuteSelectionSqlQuery(string query, IList args = null) @@ -151,6 +153,83 @@ private List ExecuteSelectionSqlQuery(string query, IList args } } + private long GetMaxPageCount() + { + return GetPragmaValue("max_page_count"); + } + + private long GetPageCount() + { + return GetPragmaValue("page_count"); + } + + private long GetPageSize() + { + return GetPragmaValue("page_size"); + } + + private long GetPragmaValue(string valueName) + { + var result = ExecuteSelectionSqlQuery($"PRAGMA {valueName};"); + var count = (long)(result.FirstOrDefault()?.FirstOrDefault() ?? 0L); + return count; + } + + public bool SetMaxStorageSize(long sizeInBytes) + { + bool success; + var db = _db ?? throw new StorageException("The database wasn't initialized."); + + // Check the current number of pages in the database to determine whether the requested size will shrink the database. + long currentPageCount = GetPageCount(); + long pageSize = GetPageSize(); + AppCenterLog.Info(AppCenterLog.LogTag, $"Found {currentPageCount} pages in the database."); + long requestedMaxPageCount = Convert.ToBoolean(sizeInBytes % pageSize) ? sizeInBytes / pageSize + 1 : sizeInBytes / pageSize; + + if (currentPageCount > requestedMaxPageCount) + { + AppCenterLog.Warn(AppCenterLog.LogTag, $"Cannot change database size to {sizeInBytes} bytes as it would cause a loss of data. " + + "Maximum database size will not be changed."); + success = false; + } + else + { + + // Attempt to set the limit and check the page count to make sure the given limit works. + int result = ExecuteNonSelectionSqlQuery($"PRAGMA max_page_count = {requestedMaxPageCount}"); + if (result != raw.SQLITE_OK) + { + AppCenterLog.Error(AppCenterLog.LogTag, $"Could not change maximum database size to {sizeInBytes} bytes. SQLite error code: {result}."); + success = false; + } + else + { + long currentMaxPageCount = GetMaxPageCount(); + long actualMaxSize = currentMaxPageCount * pageSize; + if (requestedMaxPageCount != currentMaxPageCount) + { + AppCenterLog.Error(AppCenterLog.LogTag, $"Could not change maximum database size to {sizeInBytes} bytes, current maximum size is {actualMaxSize} bytes."); + success = false; + } + else + { + if (sizeInBytes == actualMaxSize) + { + AppCenterLog.Info(AppCenterLog.LogTag, $"Changed maximum database size to {actualMaxSize} bytes."); + } + else + { + AppCenterLog.Info(AppCenterLog.LogTag, $"Changed maximum database size to {actualMaxSize} bytes (next multiple of 4KiB)."); + } + } + + success = true; + } + } + + return success; + } + public void CreateTable(string tableName, string[] columnNames, string[] columnTypes) { var tableClause = string.Join(",", Enumerable.Range(0, columnNames.Length).Select(i => $"{columnNames[i]} {columnTypes[i]}")); diff --git a/SDK/AppCenter/Microsoft.AppCenter/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter/AppCenter.cs index d540385fa..c5312b8e1 100644 --- a/SDK/AppCenter/Microsoft.AppCenter/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter/AppCenter.cs @@ -65,6 +65,11 @@ static void PlatformSetCustomProperties(CustomProperties customProperties) { } + static Task PlatformSetMaxStorageSizeAsync(long sizeInBytes) + { + return Task.FromResult(false); + } + internal static void PlatformUnsetInstance() { } From b8a6649496f6987c622281d443bc6173ca442c30 Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Mon, 16 Nov 2020 12:11:40 +0300 Subject: [PATCH 03/52] Query execution fixed --- .../Storage/StorageAdapter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs index 4ecc07022..d109d3cc6 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Storage/StorageAdapter.cs @@ -196,7 +196,7 @@ public bool SetMaxStorageSize(long sizeInBytes) { // Attempt to set the limit and check the page count to make sure the given limit works. - int result = ExecuteNonSelectionSqlQuery($"PRAGMA max_page_count = {requestedMaxPageCount}"); + int result = raw.sqlite3_exec(_db, $"PRAGMA max_page_count = {requestedMaxPageCount};"); if (result != raw.SQLITE_OK) { AppCenterLog.Error(AppCenterLog.LogTag, $"Could not change maximum database size to {sizeInBytes} bytes. SQLite error code: {result}."); From 2172194ac4711a2b5d4199b7c2e11355ebb938c7 Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Tue, 17 Nov 2020 10:40:02 +0300 Subject: [PATCH 04/52] Set size before start --- .../AppCenter.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 0ba1b95ac..719bdb3f0 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -44,6 +44,7 @@ public partial class AppCenter private string _logUrl; private bool _instanceConfigured; private string _appSecret; + private long _storageMaxSize; #region static @@ -248,7 +249,10 @@ static void PlatformStart(string appSecret, params Type[] services) static Task PlatformSetMaxStorageSizeAsync(long sizeInBytes) { - return Instance._channelGroup?.SetMaxStorageSizeAsync(sizeInBytes); + lock (AppCenterLock) + { + return Instance.SetInstanceStorageMaxSize(sizeInBytes); + } } /// @@ -320,6 +324,12 @@ private void SetInstanceLogUrl(string logUrl) _channelGroup?.SetLogUrl(logUrl); } + private Task SetInstanceStorageMaxSize(long storageMaxSize) + { + _storageMaxSize = storageMaxSize; + return _channelGroup?.SetMaxStorageSizeAsync(storageMaxSize); + } + private void SetInstanceCustomProperties(CustomProperties customProperties) { if (!Configured) @@ -342,7 +352,7 @@ private void OnUnhandledExceptionOccurred(object sender, UnhandledExceptionOccur } // Internal for testing - internal void InstanceConfigure(string appSecretOrSecrets) + internal async void InstanceConfigure(string appSecretOrSecrets) { if (_instanceConfigured) { @@ -361,6 +371,10 @@ internal void InstanceConfigure(string appSecretOrSecrets) { _channelGroup.SetLogUrl(_logUrl); } + if(_storageMaxSize > 0) + { + await _channelGroup.SetMaxStorageSizeAsync(_storageMaxSize); + } _instanceConfigured = true; AppCenterLog.Info(AppCenterLog.LogTag, "App Center SDK configured successfully."); } From 6b0c41eb6f489f8027762a9cc7b9c1e1d3821990 Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Tue, 17 Nov 2020 11:00:53 +0300 Subject: [PATCH 05/52] Configure method updated --- SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 719bdb3f0..1177a3ebc 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -352,7 +352,7 @@ private void OnUnhandledExceptionOccurred(object sender, UnhandledExceptionOccur } // Internal for testing - internal async void InstanceConfigure(string appSecretOrSecrets) + internal void InstanceConfigure(string appSecretOrSecrets) { if (_instanceConfigured) { @@ -373,7 +373,7 @@ internal async void InstanceConfigure(string appSecretOrSecrets) } if(_storageMaxSize > 0) { - await _channelGroup.SetMaxStorageSizeAsync(_storageMaxSize); + _channelGroup.SetMaxStorageSizeAsync(_storageMaxSize).GetAwaiter().GetResult(); } _instanceConfigured = true; AppCenterLog.Info(AppCenterLog.LogTag, "App Center SDK configured successfully."); From a4d788f776dd90cf45446a01d4559098d763e8dc Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Tue, 17 Nov 2020 14:47:28 +0300 Subject: [PATCH 06/52] Test apps updated --- .../Contoso.Forms.Puppet/App.xaml.cs | 4 + .../Contoso.Forms.Puppet/Constants.cs | 1 + .../ModulePages/AppCenterContentPage.xaml | 6 + .../ModulePages/AppCenterContentPage.xaml.cs | 24 ++ Apps/Contoso.UWP.Puppet/App.xaml.cs | 5 + Apps/Contoso.UWP.Puppet/MainPage.xaml | 4 + Apps/Contoso.UWP.Puppet/MainPage.xaml.cs | 28 +++ .../Contoso.WPF.Puppet.DotNetCore/App.xaml.cs | 6 + .../MainWindow.xaml | 5 +- .../MainWindow.xaml.cs | 27 +++ .../Settings.Designer.cs | 12 + .../Settings.settings | 3 + Apps/Contoso.WPF.Puppet/App.config | 3 + Apps/Contoso.WPF.Puppet/App.xaml.cs | 8 +- Apps/Contoso.WPF.Puppet/MainWindow.xaml | 3 + Apps/Contoso.WPF.Puppet/MainWindow.xaml.cs | 27 +++ .../Properties/Settings.Designer.cs | 12 + .../Properties/Settings.settings | 3 + .../MainForm.Designer.cs | 228 ++++++++++-------- .../MainForm.cs | 28 ++- .../Program.cs | 7 + .../Settings.Designer.cs | 22 +- .../Settings.settings | 3 + Apps/Contoso.WinForms.Puppet/App.config | 18 ++ .../MainForm.Designer.cs | 202 +++++++++------- Apps/Contoso.WinForms.Puppet/MainForm.cs | 27 +++ Apps/Contoso.WinForms.Puppet/MainForm.resx | 6 + Apps/Contoso.WinForms.Puppet/Program.cs | 7 + .../Properties/Settings.Designer.cs | 35 +-- .../Properties/Settings.settings | 20 +- 30 files changed, 572 insertions(+), 212 deletions(-) diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs index fa07d791b..b05d0b96a 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs @@ -81,6 +81,10 @@ protected override void OnStart() { Distribute.DisableAutomaticCheckForUpdate(); } + if (Current.Properties.ContainsKey(Constants.StorageMaxSize) && Current.Properties[Constants.StorageMaxSize] is long size) + { + AppCenter.SetMaxStorageSizeAsync(size); + } AppCenter.Start(GetTokensString(), typeof(Analytics), typeof(Crashes), typeof(Distribute)); if (Current.Properties.ContainsKey(Constants.UserId) && Current.Properties[Constants.UserId] is string id) { diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs index 2e4425a8b..704e61316 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs @@ -10,5 +10,6 @@ public static class Constants public const string UserId = "userId"; public const string UpdateTrackKey = "update-track"; public const string AutomaticUpdateCheckKey = "automatic-update-check"; + public const string StorageMaxSize = "storage-max-size"; } } diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml index 2afd00043..6783f61af 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml @@ -16,6 +16,12 @@ + + + + \ No newline at end of file diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs index 470a8518c..a230b6da1 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs @@ -34,6 +34,10 @@ protected override async void OnAppearing() { UserIdEntry.Text = id; } + if (Application.Current.Properties.ContainsKey(Constants.StorageMaxSize) && Application.Current.Properties[Constants.StorageMaxSize] is long size) + { + StorageMaxSize.Text = size.ToString(); + } UserIdEntry.Unfocused += async (sender, args) => { var inputText = UserIdEntry.Text; @@ -42,6 +46,26 @@ protected override async void OnAppearing() Application.Current.Properties[Constants.UserId] = text; await Application.Current.SavePropertiesAsync(); }; + + StorageMaxSize.Completed += async (sender, args) => + { + HandleStorageMaxSizeChanged(); + await Application.Current.SavePropertiesAsync(); + }; + + StorageMaxSize.Unfocused += async (sender, args) => + { + HandleStorageMaxSizeChanged(); + await Application.Current.SavePropertiesAsync(); + }; + } + + private void HandleStorageMaxSizeChanged() + { + var inputText = StorageMaxSize.Text; + var size = string.IsNullOrEmpty(inputText) ? 0 : long.Parse(inputText); + AppCenter.SetMaxStorageSizeAsync(size).Wait(); + Application.Current.Properties[Constants.StorageMaxSize] = size; } async void ChangeStartType(object sender, PropertyChangedEventArgs e) diff --git a/Apps/Contoso.UWP.Puppet/App.xaml.cs b/Apps/Contoso.UWP.Puppet/App.xaml.cs index 2337f3977..f63faf5bc 100644 --- a/Apps/Contoso.UWP.Puppet/App.xaml.cs +++ b/Apps/Contoso.UWP.Puppet/App.xaml.cs @@ -37,6 +37,11 @@ public App() Suspending += OnSuspending; AppCenter.LogLevel = LogLevel.Verbose; AppCenter.SetLogUrl("https://in-integration.dev.avalanch.es"); + object storageSize; + if (Windows.Storage.ApplicationData.Current.LocalSettings.Values.TryGetValue("StorageMaxSize", out storageSize)) + { + AppCenter.SetMaxStorageSizeAsync((long)storageSize); + } AppCenter.Start("42f4a839-c54c-44da-8072-a2f2a61751b2", typeof(Analytics), typeof(Crashes)); } diff --git a/Apps/Contoso.UWP.Puppet/MainPage.xaml b/Apps/Contoso.UWP.Puppet/MainPage.xaml index 2fbd5c0be..60135269c 100644 --- a/Apps/Contoso.UWP.Puppet/MainPage.xaml +++ b/Apps/Contoso.UWP.Puppet/MainPage.xaml @@ -14,5 +14,9 @@ [TestMethod] - public async Task SetMaxStorageSize() + public void SetMaxStorageSize() { var dbSize = 2 * 1024 * 1024; - _ = await AppCenter.SetMaxStorageSizeAsync(dbSize); + AppCenter.SetMaxStorageSizeAsync(dbSize); AppCenter.Start("appsecret", typeof(MockAppCenterService)); @@ -878,12 +878,12 @@ public void DontSetDefaultMaxStorageSizeOnStart() /// Verify SetMaxStorageSize can only be called before the AppCenter start. /// [TestMethod] - public async Task CannotSetMaxStorageSizeAfterStart() + public void CannotSetMaxStorageSizeAfterStart() { AppCenter.Start("appsecret", typeof(MockAppCenterService)); var dbSize = 2 * 1024 * 1024; - _ = await AppCenter.SetMaxStorageSizeAsync(dbSize); + AppCenter.SetMaxStorageSizeAsync(dbSize); _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Never()); } @@ -892,11 +892,12 @@ public async Task CannotSetMaxStorageSizeAfterStart() /// Verify that SetMaxStorageSize can only be called once. /// [TestMethod] - public async Task CannotSetMaxStorageSizeMultipleTimes() + public void CannotSetMaxStorageSizeMultipleTimes() { var dbSize = 2 * 1024 * 1024; - _ = await AppCenter.SetMaxStorageSizeAsync(dbSize); - _ = await AppCenter.SetMaxStorageSizeAsync(dbSize + 1); + AppCenter.SetMaxStorageSizeAsync(dbSize); + AppCenter.SetMaxStorageSizeAsync(dbSize + 1); + AppCenter.Start("appsecret", typeof(MockAppCenterService)); _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Once()); } @@ -905,10 +906,10 @@ public async Task CannotSetMaxStorageSizeMultipleTimes() /// Verify that dbSize param in SetMaxStorageSize should be greated than max log size. /// [TestMethod] - public async Task CannotSetMaxStorageSizeBelowMaxLogSize() + public void CannotSetMaxStorageSizeBelowMaxLogSize() { var dbSize = 10; - _ = await AppCenter.SetMaxStorageSizeAsync(dbSize); + AppCenter.SetMaxStorageSizeAsync(dbSize); _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Never()); } From 363d3e53b43d9e0e9e5c36c3f6282e629900536d Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Wed, 18 Nov 2020 10:33:52 +0300 Subject: [PATCH 11/52] Default storage size --- .../Microsoft.AppCenter.Shared/AppCenter.cs | 2 +- .../AppCenter.cs | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs index ed6360b71..c8b66dbe7 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs @@ -211,7 +211,7 @@ public static void SetCustomProperties(CustomProperties customProperties) /// Values below 20,480 bytes (20 KiB) will be ignored. /// /// true if changing the size was successful. - public static Task SetMaxStorageSizeAsync(long sizeInBytes = 1024 * 1024 * 10) + public static Task SetMaxStorageSizeAsync(long sizeInBytes) { return PlatformSetMaxStorageSizeAsync(sizeInBytes); } diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 7a566755e..b7ad33291 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -29,6 +29,7 @@ public partial class AppCenter "You need to call AppCenter.Start with appSecret or AppCenter.Configure first."; private const string ChannelName = "core"; private const long MinimumStorageSize = 1024 * 24; + private const long DefaultStorageMaxSize = 1024 * 1024 * 10; // The lock is static. Instance methods are not necessarily thread safe, but static methods are private static readonly object AppCenterLock = new object(); @@ -46,6 +47,7 @@ public partial class AppCenter private bool _instanceConfigured; private string _appSecret; private long _storageMaxSize; + private TaskCompletionSource _storageTaskCompletionSource; #region static @@ -327,23 +329,28 @@ private void SetInstanceLogUrl(string logUrl) private Task SetInstanceStorageMaxSize(long storageMaxSize) { + TaskCompletionSource resultTaskCompletionSource = new TaskCompletionSource(); if (Instance._instanceConfigured) { AppCenterLog.Error(AppCenterLog.LogTag, "SetMaxStorageSize may not be called after App Center has been configured."); - return Task.FromResult(false); + resultTaskCompletionSource.SetResult(false); + return resultTaskCompletionSource.Task; } if (_storageMaxSize > 0) { AppCenterLog.Error(AppCenterLog.LogTag, "SetMaxStorageSize may only be called once per app launch."); - return Task.FromResult(false); + resultTaskCompletionSource.SetResult(false); + return resultTaskCompletionSource.Task; } if (storageMaxSize < MinimumStorageSize) { AppCenterLog.Error(AppCenterLog.LogTag, $"Maximum storage size must be at least {MinimumStorageSize} bytes."); - return Task.FromResult(false); + resultTaskCompletionSource.SetResult(false); + return resultTaskCompletionSource.Task; } _storageMaxSize = storageMaxSize; - return _channelGroup?.SetMaxStorageSizeAsync(storageMaxSize); + _storageTaskCompletionSource = resultTaskCompletionSource; + return _storageTaskCompletionSource.Task; } private void SetInstanceCustomProperties(CustomProperties customProperties) @@ -389,7 +396,12 @@ internal void InstanceConfigure(string appSecretOrSecrets) } if(_storageMaxSize > 0) { - _channelGroup.SetMaxStorageSizeAsync(_storageMaxSize).GetAwaiter().GetResult(); + var result = _channelGroup.SetMaxStorageSizeAsync(_storageMaxSize).GetAwaiter().GetResult(); + _storageTaskCompletionSource?.SetResult(result); + } + else + { + _channelGroup.SetMaxStorageSizeAsync(DefaultStorageMaxSize).GetAwaiter().GetResult(); } _instanceConfigured = true; AppCenterLog.Info(AppCenterLog.LogTag, "App Center SDK configured successfully."); From e46a61822c6c1ed3c8fdc1b9adbf3ce7a1f8d0ab Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Wed, 18 Nov 2020 11:44:01 +0300 Subject: [PATCH 12/52] Unit tests reworked --- .../AppCenterTest.cs | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs b/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs index e4e5555b5..f8c738211 100644 --- a/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs +++ b/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs @@ -853,12 +853,12 @@ public void SetWrapperSdk() /// Verify that AppCenter forwards SetMaxStorageSize to its channelGroup. /// [TestMethod] - public void SetMaxStorageSize() + public async Task SetMaxStorageSize() { var dbSize = 2 * 1024 * 1024; - AppCenter.SetMaxStorageSizeAsync(dbSize); - + var storageTask = AppCenter.SetMaxStorageSizeAsync(dbSize); AppCenter.Start("appsecret", typeof(MockAppCenterService)); + await storageTask; _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Once()); } @@ -867,23 +867,23 @@ public void SetMaxStorageSize() /// Verify default value for max storage size is not set on AppCenter start. /// [TestMethod] - public void DontSetDefaultMaxStorageSizeOnStart() + public void SetDefaultMaxStorageSizeOnStart() { AppCenter.Start("appsecret", typeof(MockAppCenterService)); - _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(10 * 1024 * 1024), Times.Never()); + _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(10 * 1024 * 1024), Times.Once()); } /// /// Verify SetMaxStorageSize can only be called before the AppCenter start. /// [TestMethod] - public void CannotSetMaxStorageSizeAfterStart() + public async Task CannotSetMaxStorageSizeAfterStart() { AppCenter.Start("appsecret", typeof(MockAppCenterService)); var dbSize = 2 * 1024 * 1024; - AppCenter.SetMaxStorageSizeAsync(dbSize); + await AppCenter.SetMaxStorageSizeAsync(dbSize); _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Never()); } @@ -892,12 +892,14 @@ public void CannotSetMaxStorageSizeAfterStart() /// Verify that SetMaxStorageSize can only be called once. /// [TestMethod] - public void CannotSetMaxStorageSizeMultipleTimes() + public async Task CannotSetMaxStorageSizeMultipleTimes() { var dbSize = 2 * 1024 * 1024; - AppCenter.SetMaxStorageSizeAsync(dbSize); - AppCenter.SetMaxStorageSizeAsync(dbSize + 1); + var taskFirst = AppCenter.SetMaxStorageSizeAsync(dbSize); + var taskSecond = AppCenter.SetMaxStorageSizeAsync(dbSize + 1); AppCenter.Start("appsecret", typeof(MockAppCenterService)); + await taskFirst; + await taskSecond; _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Once()); } @@ -906,10 +908,10 @@ public void CannotSetMaxStorageSizeMultipleTimes() /// Verify that dbSize param in SetMaxStorageSize should be greated than max log size. /// [TestMethod] - public void CannotSetMaxStorageSizeBelowMaxLogSize() + public async Task CannotSetMaxStorageSizeBelowMaxLogSize() { var dbSize = 10; - AppCenter.SetMaxStorageSizeAsync(dbSize); + await AppCenter.SetMaxStorageSizeAsync(dbSize); _channelGroupMock.Verify(channelGroup => channelGroup.SetMaxStorageSizeAsync(dbSize), Times.Never()); } From f017585e7c6faf02d80153e02d7ca76e2100ee58 Mon Sep 17 00:00:00 2001 From: Oleg Misal Date: Wed, 18 Nov 2020 12:08:01 +0300 Subject: [PATCH 13/52] Revert "Test apps updated" This reverts commit a4d788f776dd90cf45446a01d4559098d763e8dc. --- .../Contoso.Forms.Puppet/App.xaml.cs | 4 - .../Contoso.Forms.Puppet/Constants.cs | 1 - .../ModulePages/AppCenterContentPage.xaml | 6 - .../ModulePages/AppCenterContentPage.xaml.cs | 24 -- Apps/Contoso.UWP.Puppet/App.xaml.cs | 5 - Apps/Contoso.UWP.Puppet/MainPage.xaml | 4 - Apps/Contoso.UWP.Puppet/MainPage.xaml.cs | 28 --- .../Contoso.WPF.Puppet.DotNetCore/App.xaml.cs | 6 - .../MainWindow.xaml | 5 +- .../MainWindow.xaml.cs | 27 --- .../Settings.Designer.cs | 12 - .../Settings.settings | 3 - Apps/Contoso.WPF.Puppet/App.config | 3 - Apps/Contoso.WPF.Puppet/App.xaml.cs | 8 +- Apps/Contoso.WPF.Puppet/MainWindow.xaml | 3 - Apps/Contoso.WPF.Puppet/MainWindow.xaml.cs | 27 --- .../Properties/Settings.Designer.cs | 12 - .../Properties/Settings.settings | 3 - .../MainForm.Designer.cs | 228 ++++++++---------- .../MainForm.cs | 28 +-- .../Program.cs | 7 - .../Settings.Designer.cs | 22 +- .../Settings.settings | 3 - Apps/Contoso.WinForms.Puppet/App.config | 18 -- .../MainForm.Designer.cs | 202 +++++++--------- Apps/Contoso.WinForms.Puppet/MainForm.cs | 27 --- Apps/Contoso.WinForms.Puppet/MainForm.resx | 6 - Apps/Contoso.WinForms.Puppet/Program.cs | 7 - .../Properties/Settings.Designer.cs | 35 ++- .../Properties/Settings.settings | 20 +- 30 files changed, 212 insertions(+), 572 deletions(-) diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs index b05d0b96a..fa07d791b 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/App.xaml.cs @@ -81,10 +81,6 @@ protected override void OnStart() { Distribute.DisableAutomaticCheckForUpdate(); } - if (Current.Properties.ContainsKey(Constants.StorageMaxSize) && Current.Properties[Constants.StorageMaxSize] is long size) - { - AppCenter.SetMaxStorageSizeAsync(size); - } AppCenter.Start(GetTokensString(), typeof(Analytics), typeof(Crashes), typeof(Distribute)); if (Current.Properties.ContainsKey(Constants.UserId) && Current.Properties[Constants.UserId] is string id) { diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs index 704e61316..2e4425a8b 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Constants.cs @@ -10,6 +10,5 @@ public static class Constants public const string UserId = "userId"; public const string UpdateTrackKey = "update-track"; public const string AutomaticUpdateCheckKey = "automatic-update-check"; - public const string StorageMaxSize = "storage-max-size"; } } diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml index 6783f61af..2afd00043 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml @@ -16,12 +16,6 @@ - - - - \ No newline at end of file diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs index a230b6da1..470a8518c 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/ModulePages/AppCenterContentPage.xaml.cs @@ -34,10 +34,6 @@ protected override async void OnAppearing() { UserIdEntry.Text = id; } - if (Application.Current.Properties.ContainsKey(Constants.StorageMaxSize) && Application.Current.Properties[Constants.StorageMaxSize] is long size) - { - StorageMaxSize.Text = size.ToString(); - } UserIdEntry.Unfocused += async (sender, args) => { var inputText = UserIdEntry.Text; @@ -46,26 +42,6 @@ protected override async void OnAppearing() Application.Current.Properties[Constants.UserId] = text; await Application.Current.SavePropertiesAsync(); }; - - StorageMaxSize.Completed += async (sender, args) => - { - HandleStorageMaxSizeChanged(); - await Application.Current.SavePropertiesAsync(); - }; - - StorageMaxSize.Unfocused += async (sender, args) => - { - HandleStorageMaxSizeChanged(); - await Application.Current.SavePropertiesAsync(); - }; - } - - private void HandleStorageMaxSizeChanged() - { - var inputText = StorageMaxSize.Text; - var size = string.IsNullOrEmpty(inputText) ? 0 : long.Parse(inputText); - AppCenter.SetMaxStorageSizeAsync(size).Wait(); - Application.Current.Properties[Constants.StorageMaxSize] = size; } async void ChangeStartType(object sender, PropertyChangedEventArgs e) diff --git a/Apps/Contoso.UWP.Puppet/App.xaml.cs b/Apps/Contoso.UWP.Puppet/App.xaml.cs index f63faf5bc..2337f3977 100644 --- a/Apps/Contoso.UWP.Puppet/App.xaml.cs +++ b/Apps/Contoso.UWP.Puppet/App.xaml.cs @@ -37,11 +37,6 @@ public App() Suspending += OnSuspending; AppCenter.LogLevel = LogLevel.Verbose; AppCenter.SetLogUrl("https://in-integration.dev.avalanch.es"); - object storageSize; - if (Windows.Storage.ApplicationData.Current.LocalSettings.Values.TryGetValue("StorageMaxSize", out storageSize)) - { - AppCenter.SetMaxStorageSizeAsync((long)storageSize); - } AppCenter.Start("42f4a839-c54c-44da-8072-a2f2a61751b2", typeof(Analytics), typeof(Crashes)); } diff --git a/Apps/Contoso.UWP.Puppet/MainPage.xaml b/Apps/Contoso.UWP.Puppet/MainPage.xaml index 60135269c..2fbd5c0be 100644 --- a/Apps/Contoso.UWP.Puppet/MainPage.xaml +++ b/Apps/Contoso.UWP.Puppet/MainPage.xaml @@ -14,9 +14,5 @@