diff --git a/src/Controllers/SettingsController.cs b/src/Controllers/SettingsController.cs index 2bf2d9b..713cc57 100644 --- a/src/Controllers/SettingsController.cs +++ b/src/Controllers/SettingsController.cs @@ -56,9 +56,29 @@ public class SettingsController : Controller ErrorMessage = "adminUpdateRequestModel is null" }; } + AdminSettingsModel currentSettingsModel = await _ldap.GetAdminSettingsModelAsync(); await _ldap.SetAdminSettingsModelAsync(adminSettingsRequestModel.AdminSettingsModel); + if (adminSettingsRequestModel.AdminSettingsModel.UserImagePreloadType != UserImagePreloadType.None) + { + IEnumerable users = await _ldap.ListUsersAsync(); + Task _ = ImageHelper.PreloadUsers(users, adminSettingsRequestModel.AdminSettingsModel.UserImagePreloadType); + } return new() { Success = true }; } + + [Authorize(Roles = "CanManageSettings")] + [HttpPost("ClearUserImageCache")] + public bool ClearUserImageCache() + { + ImageHelper.ImageCache = []; + return true; + } + [Authorize(Roles = "CanManageSettings")] + [HttpPost("UserImageCacheSize")] + public string UserImageCacheSize() + { + return ImageHelper.ToHumanReadableSize(ImageHelper.GetImageCacheSize()); + } } \ No newline at end of file diff --git a/src/Helpers/ImageHelper.cs b/src/Helpers/ImageHelper.cs index 9124e81..e0baa08 100644 --- a/src/Helpers/ImageHelper.cs +++ b/src/Helpers/ImageHelper.cs @@ -10,6 +10,7 @@ public static class ImageHelper public static Dictionary> ImageCache = []; public static byte[] ResizeAndConvertToWebp(string imageString, int size = 32) { + if (imageString.Length == 0) return []; if (ImageCache.TryGetValue(size, out Dictionary? sizeCache) && sizeCache.TryGetValue(imageString, out byte[]? result) && result.Length > 0) { @@ -49,6 +50,69 @@ public static class ImageHelper { ResizeAndConvertToWebp(user.JpegPhoto, 256); } + Thread.Sleep(10); } } + + public static long GetImageCacheSize() + { + long size = 0; + int stringOverhead = GetStringOverhead(); + int arrayOverhead = GetArrayOverhead(); + foreach (var kvOuter in ImageCache) + { + foreach (var kvInner in kvOuter.Value) + { + size += System.Text.ASCIIEncoding.Unicode.GetByteCount(kvInner.Key); + size += stringOverhead; + + // byte[] size + if (kvInner.Value != null) + size += kvInner.Value.Length + arrayOverhead; + } + } + return size; + } + + public static string ToHumanReadableSize(long bytes) + { + string[] sizes = ["B", "KB", "MB", "GB", "TB", "PB"]; + double len = bytes; + int order = 0; + + while (len >= 1024 && order < sizes.Length - 1) + { + order++; + len /= 1024; + } + + return $"{len:0.##} {sizes[order]}"; + } + + private static int GetStringOverhead() + { + // Object header size + int header = IntPtr.Size == 8 ? 16 : 8; // 16 bytes on x64, 8 on x86 + + int size = + header + + sizeof(int) + // string length field + sizeof(char); // null terminator + + return size; + } + + private static int GetArrayOverhead() + { + // On x64 object header = 16 bytes; on x86 = 8 bytes + int header = IntPtr.Size == 8 ? 16 : 8; + + // Array length field = 4 bytes + int lengthField = sizeof(int); + + // Padding on x64 to align the elements (so the first element is aligned) + int padding = IntPtr.Size == 8 ? 4 : 0; + + return header + lengthField + padding; + } } \ No newline at end of file diff --git a/src/Resources/Views.Settings.Admin.de.resx b/src/Resources/Views.Settings.Admin.de.resx index 5f9ba22..1dc9306 100644 --- a/src/Resources/Views.Settings.Admin.de.resx +++ b/src/Resources/Views.Settings.Admin.de.resx @@ -101,4 +101,13 @@ 48x48 + 256x256 + + Cache wurde erfolgreich geleert. + + + Aktuell durch den Cache belegt: + + + Cache leeren + diff --git a/src/Services/ImagePreloadService.cs b/src/Services/ImagePreloadService.cs index 0a3b2d3..41c883e 100644 --- a/src/Services/ImagePreloadService.cs +++ b/src/Services/ImagePreloadService.cs @@ -20,7 +20,7 @@ public class ImagePreloadService : IHostedService if (adminSettingsModel.UserImagePreloadType is not null && adminSettingsModel.UserImagePreloadType != UserImagePreloadType.None) { IEnumerable users = _ldap.ListUsersAsync().Result; - _logger.LogTrace("Preloading user images"); + _logger.LogInformation("Preloading user images with preload type {adminSettingsModel.UserImagePreloadType}", [adminSettingsModel.UserImagePreloadType]); return ImageHelper.PreloadUsers(users, adminSettingsModel.UserImagePreloadType); } return Task.CompletedTask; diff --git a/src/Views/Settings/Admin.cshtml b/src/Views/Settings/Admin.cshtml index 1cff310..c3c748c 100644 --- a/src/Views/Settings/Admin.cshtml +++ b/src/Views/Settings/Admin.cshtml @@ -1,3 +1,4 @@ +@using Berufsschule_HAM.Helpers @using Berufsschule_HAM.Services @using Microsoft.AspNetCore.Html @using Microsoft.AspNetCore.Mvc.Localization @@ -11,12 +12,13 @@ @{ ViewData["Title"] = T["Users"]; List supportedBarcodeTypes = ["code128c", "ean13", "ean8", "upc", "itf14", "itf"]; + string userImageCacheSize = ImageHelper.ToHumanReadableSize(ImageHelper.GetImageCacheSize()); }

@T["General settings"]

-
+
-
+
-
+
-
+
-
+
+
+

@T["Current user image cache utilization:"] @userImageCacheSize

+ +