/// <summary> /// Attempts to increase the <see cref="PageCapacity"/> of the base <see cref="PageStorage"/> /// by creating space for more unallocated pages. /// </summary> /// <param name="additionalPageCount">The desired additional number of unallocated /// pages to create.</param> /// <param name="progressReporter"><see cref="IProgress{T}"/> that receives a /// <see cref="ProgressReport"/> as the inflation progresses. May be null, in /// which case progress will not be reported.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> that allows /// the application to cancel the inflation. Cancellation will cause the inflation /// to stop at the nearest 'safe' position to avoid data corruption. This means /// that some pages may have already been created upon cancellation, but not /// necessarily as many as were requested. Upon cancellation, this method will /// NOT throw any <see cref="Exception"/>, but will instead return the additional /// number of pages that have been created, if any, before the operation was /// cancelled.</param> /// <returns>The actual number of additional unallocated pages that were created. /// This may be more or less than the desired <paramref name="additionalPageCount"/>, /// and may even be zero.</returns> /// <remarks> /// <para> /// This method will simply call the <see cref="IPageStorage.TryInflate(long, IProgress{ProgressReport}, CancellationToken)"/> /// method of the base <see cref="PageStorage"/>. Cache will not be affected. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsCapacityFixed"/> /// is true.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="additionalPageCount"/> /// is less than zero.</exception> /// <seealso cref="IsCapacityFixed"/> /// <seealso cref="PageCapacity"/> /// <seealso cref="TryDeflate(long, IProgress{ProgressReport}, CancellationToken)"/> public long TryInflate(long additionalPageCount, IProgress <ProgressReport> progressReporter, CancellationToken cancellationToken) { if (IsCapacityFixed) { throw new InvalidOperationException("Cannot inflate a fixed-capacity " + nameof(CachedPageStorage) + "."); } if (additionalPageCount < 0) { throw new ArgumentOutOfRangeException(nameof(additionalPageCount), "Cannot inflate by a negative number of pages."); } lock (locker) { long ret = PageStorage.TryInflate(additionalPageCount, progressReporter, cancellationToken); return(ret); } }
/// <summary> /// Writes payload to an allocated page. /// </summary> /// <param name="pageIndex">The index of the allocated page.</param> /// <param name="dstOffset">The destination offset within the page's payload, measured in /// bytes.</param> /// <param name="buffer">The source buffer.</param> /// <param name="srcOffset">The source offset within the source <paramref name="buffer"/>, /// measured in bytes.</param> /// <param name="length">The number of bytes to write.</param> /// <remarks> /// <para> /// If the page is not loaded into cache, it will be loaded (but not read, as read is not /// necessary for this method). The data will be written into the cached page (unless cache /// failed or <see cref="CachedPageCapacity"/> is zero), and then if <see cref="Mode"/> is /// <see cref="CacheWriteMode.WriteThrough"/> the data will also be immediately written to /// the base <see cref="PageStorage"/>. If <see cref="Mode"/> is <see cref="CacheWriteMode.WriteBack"/>, /// then data will be written to the base <see cref="PageStorage"/> at a later time (when the /// internal buffers get too full, or when the page is evicted from cache, or when <see cref="Flush"/> /// or <see cref="Dispose"/> is called). If caching fails, or if <see cref="CachedPageCapacity"/> /// is zero, then the data will be immediately written directly to the base <see cref="PageStorage"/> /// regardless of the <see cref="Mode"/>. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <paramref name="pageIndex"/> refers /// to an unallocated page, or if <see cref="IsReadOnly"/> is true. /// </exception> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="srcOffset"/>, /// <paramref name="dstOffset"/>, or <paramref name="length"/> is negative; or if /// the sum of <paramref name="dstOffset"/> and <paramref name="length"/> is greater /// than <see cref="PageSize"/>; or if the sum of <paramref name="srcOffset"/> and /// <paramref name="length"/> is greater than the <paramref name="buffer"/> size. /// </exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="buffer"/> is null.</exception> /// <seealso cref="ReadFrom(long, long, byte[], long, long)"/> /// <seealso cref="IsReadOnly"/> /// <seealso cref="IsPageAllocated(long)"/> public void WriteTo(long pageIndex, long dstOffset, byte[] buffer, long srcOffset, long length) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (IsReadOnly) { throw new InvalidOperationException("Cannot write to any page on a read-only " + nameof(CachedPageStorage) + "."); } if (dstOffset < 0) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The destination offset cannot be less than zero."); } if (srcOffset < 0) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The source offset cannot be less than zero."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "The length cannot be less than zero."); } if (dstOffset + length > PageSize) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The sum of the destination offset and length cannot be greater than " + nameof(PageSize) + "."); } if (srcOffset + length > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The sum of the source offset and length cannot be greater than the size of the source buffer ."); } if (TryGetCachedPage(pageIndex, out var cachedPage)) { cachedPage.Write(dstOffset, buffer, srcOffset, length); } else { if (!IsPageAllocated(pageIndex)) { throw new InvalidOperationException("Cannot write to an unallocated page."); } PageStorage.WriteTo(pageIndex, dstOffset, buffer, srcOffset, length);//Failed to use cache, so write directly to base IPageStorage } }
public void lookup_paths_for_a_document_id() { var storage = new MemoryStream(); var subject = new PageStorage(storage); var target = Guid.NewGuid(); subject.BindPath("one", target, out _); subject.BindPath("two", Guid.NewGuid(), out _); subject.BindPath("three", target, out _); subject.BindPath("four", target, out _); subject.BindPath("five", Guid.NewGuid(), out _); subject.BindPath("six", Guid.NewGuid(), out _); var list = string.Join(",", subject.GetPathsForDocument(target)); Assert.That(list, Is.EqualTo("one,three,four")); }
/// <summary> /// Disposes this <see cref="CachedPageStorage"/>, sending any cached write operations /// to the base <see cref="PageStorage"/>. /// </summary> /// <remarks> /// <para> /// This method will result in a call to <see cref="Flush"/> to ensure that any cached write /// operations are sent to the base <see cref="PageStorage"/>. /// </para> /// <para> /// If <see cref="WillLeaveBasePageStorageOpen"/> is false, then this method will dispose the /// base <see cref="PageStorage"/>. /// </para> /// </remarks> /// <seealso cref="IsDisposed"/> public void Dispose() { lock (locker) { if (!IsDisposed) { //Send any cached writes to the base IPageStorage Flush(); if (!WillLeaveBasePageStorageOpen) { PageStorage.Dispose(); } IsDisposed = true; } } }
public void ThenAllSublinksOfShopProductsShouldDisplay() { WaitHelper.WaitUntil(() => PageStorage.GetPage <HomePage>().Sub_Menu_Regimens_and_Kits_Link.Displayed); Actions actions = new Actions(PageStorage.Driver); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Regimens_and_Kits_Link).Perform(); Thread.Sleep(1000); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Moisturizers_Link).Perform(); Thread.Sleep(1000); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Anti_Aging_Treatments_Link).Perform(); Thread.Sleep(1000); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Cleansers_Toners_Link).Perform(); Thread.Sleep(1000); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Serums_Link).Perform(); Thread.Sleep(1000); actions.MoveToElement(PageStorage.GetPage <HomePage>().Sub_Menu_Eyes_Lips_Link).Perform(); Thread.Sleep(1000); }
public void unbinding_paths() { var storage = new MemoryStream(); var subject = new PageStorage(storage); subject.BindPath("find me/one", Guid.NewGuid(), out _); subject.BindPath("find me/two", Guid.NewGuid(), out _); subject.BindPath("miss me/three", Guid.NewGuid(), out _); subject.BindPath("find me/four", Guid.NewGuid(), out _); subject.BindPath("miss me/five", Guid.NewGuid(), out _); subject.BindPath("miss me/six", Guid.NewGuid(), out _); subject.UnbindPath("find me/one"); subject.UnbindPath("find me/four"); var list = string.Join(",", subject.SearchPaths("find me/")); Assert.That(list, Is.EqualTo("find me/two")); }
public async Task DownloadEbookAsync(Ebook ebook) { switch (ebook.Publisher) { case "Liber": try { LiberOnlinebokDocument document; LiberOnlinebokAssetsClient assetsClient; using (LiberOnlinebokClient liberClient = await _hermodsNovoClient.GetLiberOnlinebokClientAsync(ebook.ProviderAttributes["url"])) { document = await liberClient.GetDocumentAsync(); assetsClient = await liberClient.GetAssetsClientAsync(); } using (assetsClient) { var pageAssets = document.Content.ContentItems.Select(ci => (ci.OrderingIndex, ci.Assets.First().Uri)).ToArray(); foreach (var asset in pageAssets) { var ebookPage = await assetsClient.GetAssetAsync(asset.Uri); await PageStorage.SavePageAsync(ebook, ebookPage, asset.OrderingIndex); Messenger.Default.Send(new DownloadStatusMessage(Array.IndexOf(pageAssets, asset), pageAssets.Length), ebook.Isbn); } } } catch (Exception e) { throw new EbookDownloadException(ebook, e); } break; default: throw new EbookPublisherNotImplementedException(ebook); } }
public async Task Dispose_ThreePagesRequested_AllThreePagesDisposed() { // Arrange var page = Substitute.For<IPage<int>>(); page.ReturnsForAll(69); var sut = new PageStorage<int>( 10, 10000, (_, __, ___, ____) => page, _ => Observable.Never<IReadOnlyList<int>>()); // Act var i = sut[69]; var i1 = sut[23]; var i2 = sut[3]; await sut.DisposeAsync().ConfigureAwait(false); // Assert await page.Received(Quantity.Exactly(3)).DisposeAsync(); }
public override void initState() { base.initState(); this._controller = new AnimationController(duration: ExpansionTileUtils._kExpand, vsync: this); this._heightFactor = this._controller.drive(_easeInTween); this._iconTurns = this._controller.drive(_halfTween.chain(_easeInTween)); this._borderColor = this._controller.drive(this._borderColorTween.chain(_easeOutTween)); this._headerColor = this._controller.drive(this._headerColorTween.chain(_easeInTween)); this._iconColor = this._controller.drive(this._iconColorTween.chain(_easeInTween)); this._backgroundColor = this._controller.drive(this._backgroundColorTween.chain(_easeOutTween)); this._isExpanded = PageStorage.of(this.context)?.readState(this.context) == null ? this.widget.initiallyExpanded : (bool)PageStorage.of(this.context)?.readState(this.context); if (this._isExpanded) { this._controller.setValue(1.0); } }
/// <summary> /// Reads payload from an allocated page. /// </summary> /// <param name="pageIndex">The index of the allocated page.</param> /// <param name="srcOffset">The source offset within the page's payload, measured in bytes.</param> /// <param name="buffer">The destination buffer.</param> /// <param name="dstOffset">The destination offset within the destination <paramref name="buffer"/>, /// measured in bytes.</param> /// <param name="length">The number of bytes to read.</param> /// <remarks> /// <para> /// If any of the requested data is not currently cached, it will be loaded into cache (unless /// <see cref="CachedPageCapacity"/> is zero). Then, the cached data will be copied into the /// destination <paramref name="buffer"/>. If cache fails due to insufficient memory, or if /// <see cref="CachedPageCapacity"/> is zero, then this method will bypass cache and read /// directly from the base <see cref="PageStorage"/>. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <paramref name="pageIndex"/> does not refer to /// an allocated page. /// </exception> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="srcOffset"/>, /// <paramref name="dstOffset"/>, or <paramref name="length"/> is negative; or if the sum of /// <paramref name="srcOffset"/> and <paramref name="length"/> is greater than <see cref="PageSize"/>; /// or if the sum of <paramref name="dstOffset"/> and <paramref name="length"/> is greater than /// the <paramref name="buffer"/> size. /// </exception> /// <exception cref="ArgumentNullException">Thrown if <paramref name="buffer"/> is null.</exception> /// <seealso cref="WriteTo(long, long, byte[], long, long)"/> /// <seealso cref="IsPageAllocated(long)"/> public void ReadFrom(long pageIndex, long srcOffset, byte[] buffer, long dstOffset, long length) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (srcOffset < 0) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The source offset cannot be less than zero."); } if (dstOffset < 0) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The destination offset cannot be less than zero."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "The length cannot be less than zero."); } if (srcOffset + length > PageSize) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The sum of the source offset and length cannot be greater than " + nameof(PageSize) + "."); } if (dstOffset + length > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The sum of the destination offset and length cannot be greater than the length of the destination buffer.", nameof(dstOffset)); } if (TryGetCachedPage(pageIndex, out var cachedPage)) { cachedPage.Read(srcOffset, buffer, dstOffset, length); } else { if (!IsPageAllocated(pageIndex)) { throw new InvalidOperationException("Cannot read from an unallocated page."); } PageStorage.ReadFrom(pageIndex, srcOffset, buffer, dstOffset, length);//Failed to use cache, so read directly from base IPageStorage } }
public async Task PageRemoval_RemoveAllExceptFirstRequestedPage_TwoPagesDisposed() { // Arrange var page = Substitute.For<IPage<int>>(); page.ReturnsForAll(69); var subject = new Subject<IReadOnlyList<int>>(); await using var sut = new PageStorage<int>( 10, 10000, (_, __, ___, ____) => page, _ => subject); // Act var i = sut[69]; var i1 = sut[23]; var i2 = sut[3]; subject.OnNext(new []{ 0, 2 }); // Assert await page.Received(Quantity.Exactly(2)).DisposeAsync(); }
public void cycling_page_usage() { var storage = new MemoryStream(); var sampleData = new byte[] { 1, 4, 7, 2, 5, 8, 3, 6, 9 }; var sampleDataStream = new MemoryStream(sampleData); sampleDataStream.Seek(0, SeekOrigin.Begin); var subject = new PageStorage(storage); Console.WriteLine($"Storage after headers is {storage.Length} bytes"); for (int i = 0; i < 10; i++) { sampleDataStream.Seek(0, SeekOrigin.Begin); var pageId = subject.WriteStream(sampleDataStream); subject.ReleaseChain(pageId); } Console.WriteLine($"Storage after writing data is {storage.Length} bytes"); }
private bool TryGetCachedPage(long pageIndex, out CachedPage cachedPage) { lock (locker) { if (CachedPageCapacity == 0) { cachedPage = null; return(false); } if (!cachedPages.TryGetValue(pageIndex, out cachedPage)) { //The page is not yet in cache if (PageStorage.IsPageAllocated(pageIndex)) { try { cachedPage = AddPageToCache(pageIndex); return(true); } catch (OutOfMemoryException) { cachedPage = null; return(false); } } else { //The page is not allocated, cannot cache it cachedPage = null; return(false); } } else { return(true); } } }
/// <summary> /// Deallocates a page. /// </summary> /// <param name="index">The index of the page to deallocate.</param> /// <returns>True if the page was deallocated, false if it was already /// unallocated when this method was called.</returns> /// <remarks> /// <para> /// Before freeing the page, this method will ensure that any pending /// write operations are sent to the base <see cref="PageStorage"/>. This /// may be important for security cases where the application was storing /// sensitive data that it wishes to overwrite before freeing the page. After /// cache is flushed, the <see cref="IPageStorage.FreePage(long)"/> method of /// the base <see cref="PageStorage"/> will be called. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsReadOnly"/> is true.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="index"/> is negative or /// greater than or equal to <see cref="PageCapacity"/>. See <see cref="IsPageOnStorage(long)"/>.</exception> /// <seealso cref="TryAllocatePage(out long)"/> /// <seealso cref="IsReadOnly"/> /// <seealso cref="IsPageAllocated(long)"/> /// <seealso cref="AllocatedPageCount"/> public bool FreePage(long index) { lock (locker) { if (IsReadOnly) { throw new InvalidOperationException("Cannot free a page on a read-only " + nameof(CachedPageStorage) + "."); } if (!IsPageOnStorage(index)) { throw new ArgumentOutOfRangeException(nameof(index), "The index refers to a page which does not exist on the base " + nameof(IPageStorage) + "."); } //First, evict the page from cache (assuming it is cached). //Note that this may cause any pending writes to be sent to the base PageStorage. //This is intended! The application may have overwritten sensitive data. EvictPageFromCache(index); bool ret = PageStorage.FreePage(index); return(ret); } }
private static async Task <string> _getThumbnailPathAsync(Ebook ebook, int page = 1) { var thumbnailFile = await ApplicationData.Current.LocalFolder.CreateFileAsync($"tiles\\thumbnails\\{ebook.Isbn}.jpg", CreationCollisionOption.OpenIfExists); var properties = await thumbnailFile.GetBasicPropertiesAsync(); if (properties.Size == 0) { var pageFile = await PageStorage.GetPageFileAsync(ebook, page); var thumbnail = await pageFile.GetScaledImageAsThumbnailAsync(ThumbnailMode.DocumentsView, 150); using (var stream = thumbnail.AsStreamForRead()) using (var outStream = await thumbnailFile.OpenStreamForWriteAsync()) { stream.Position = 0; await stream.CopyToAsync(outStream); await outStream.FlushAsync(); } } return("ms-appdata:///local/tiles/thumbnails/" + thumbnailFile.Name); }
public void removing_from_index() { var storage = new MemoryStream(); var subject = new PageStorage(storage); var newPageId = 123; var otherPageId = 321; var docId = Guid.NewGuid(); var otherId = Guid.NewGuid(); subject.BindIndex(docId, newPageId, out var oldPageId); subject.BindIndex(otherId, otherPageId, out _); var result = subject.GetDocumentHead(docId); Assert.That(result, Is.EqualTo(newPageId)); Assert.That(oldPageId, Is.EqualTo(-1)); subject.UnbindIndex(docId); Assert.That(subject.GetDocumentHead(docId), Is.EqualTo(-1), "Document is still in the index"); Assert.That(subject.GetDocumentHead(otherId), Is.EqualTo(otherPageId), "Lost a document we didn't target"); }
public SettingsPage(PageStorage <SettingsData> settingsData) : base("div") { bool useSafeLoading = false; if (settingsData.TryLoad() == false) { settingsData.UseSafeLoading(); useSafeLoading = true; } if (PageStorage <HumiditySensorData> .Instance.TryLoad() == false) { PageStorage <HumiditySensorData> .Instance.UseSafeLoading(); useSafeLoading = true; } this.AddScriptDependency("/lib/bootstrap3-typeahead.min.js"); const int labelSize = 180; _settingsData = settingsData; #region Initialize Grid Container wrappingContainer = new Container(this); Grid grid = new Grid(wrappingContainer); grid.AddStyling(StylingOption.MarginRight, 2); grid.AddStyling(StylingOption.MarginLeft, 2); grid.AddStyling(StylingOption.MarginTop, 4); grid.AddStyling(StylingOption.MarginBottom, 2); #endregion Initialize Grid if (useSafeLoading) { grid.AddRow().AppendCollum(new Heading(3, "Wegen Verbindungsproblemem wurden keine Daten geladen!") { Style = { Color = Color.Red } }); } #region AutoEnabled MultiInputGroup autoEnabledMultiInputGroup = new MultiInputGroup(); autoEnabledMultiInputGroup.AppendLabel("Automatik", labelSize); autoEnabledMultiInputGroup .AppendCustomElement( new TwoStateButtonGroup("Aktiv", "Inaktiv", settingsData.StorageData.Enabled, !settingsData.StorageData.Enabled), false).FirstButtonStateChange += (sender, args) => settingsData.StorageData.Enabled = args.NewButtonState; autoEnabledMultiInputGroup.AddStyling(StylingOption.MarginBottom, 2); autoEnabledMultiInputGroup.AppendCustomElement(new Button(StylingColor.Danger, true, Button.ButtonSize.Normal, false, "Alle Kanäle ausschalten", fontAwesomeIcon: "stop"), false).Click += (sender, args) => { ServerConnection.DeleteAsync("settings", "stopall"); }; grid.AddRow().AppendCollum(autoEnabledMultiInputGroup, autoSize: true); #endregion AutoEnabled #region WeatherEnabled MultiInputGroup weatherEnabledMultiInputGroup = new MultiInputGroup(); weatherEnabledMultiInputGroup.AppendLabel("Wetterdaten verwenden", labelSize); weatherEnabledMultiInputGroup .AppendCustomElement( new TwoStateButtonGroup("Aktiv", "Inaktiv", settingsData.StorageData.WeatherEnabled, !settingsData.StorageData.WeatherEnabled), false).FirstButtonStateChange += (sender, args) => settingsData.StorageData.WeatherEnabled = args.NewButtonState; weatherEnabledMultiInputGroup.AddStyling(StylingOption.MarginBottom, 2); grid.AddRow().AppendCollum(weatherEnabledMultiInputGroup, autoSize: true); #endregion WeatherEnabled #region Location Row locationRow = grid.AddRow(); locationRow.AddStyling(StylingOption.MarginBottom, 2); MultiInputGroup weatherLocationMultiInputGroup = new MultiInputGroup(); weatherLocationMultiInputGroup.AppendLabel("Standort", labelSize); StylableTextInput weatherLocationTextInput = weatherLocationMultiInputGroup.AppendTextInput("Bitte Eintragen...", false); weatherLocationTextInput.Value = settingsData.StorageData.LocationFriendlyName; #region Hidden TextInputs TextInput weatherLocationChangeTextInput = new TextInput { IsHidden = true, Value = settingsData.StorageData.Location }; locationRow.AppendChild(weatherLocationChangeTextInput); TextInput weatherLocationNameChangeTextInput = new TextInput { IsHidden = true, Value = settingsData.StorageData.LocationFriendlyName }; locationRow.AppendChild(weatherLocationNameChangeTextInput); #endregion Hidden TextInputs #region Autocomplete weatherLocationTextInput.ActivateAutocomplete("/settings/WeatherLocations.json", new Dictionary <string, TextInput>() { { "location", weatherLocationChangeTextInput }, { "name", weatherLocationNameChangeTextInput } }); #endregion Autocomplete locationRow.AppendCollum(weatherLocationMultiInputGroup, autoSize: true); #region Save Button Button saveLocationButton = new Button(StylingColor.Success, true, text: "Übernehmen"); saveLocationButton.Click += (sender, args) => { if (weatherLocationChangeTextInput.Value == "") { weatherLocationTextInput.SetValidation(false, true); } else { weatherLocationTextInput.SetValidation(false, false); settingsData.StorageData.Location = weatherLocationChangeTextInput.Value; settingsData.StorageData.LocationFriendlyName = weatherLocationNameChangeTextInput.Value; weatherLocationTextInput.Value = settingsData.StorageData.LocationFriendlyName; } }; locationRow.AppendCollum(saveLocationButton, autoSize: true); #endregion Save Button #endregion Location #region Override _overrideInputGroup = new OverrideInputGroup(_settingsData.StorageData.OverrideValue, labelSizeInPx: labelSize); grid.AddRow().AppendCollum(_overrideInputGroup, autoSize: true); #endregion Override #region Rename HumiditySensors Row humidityRow = grid.AddRow(); humidityRow.AppendChild(new Heading(3, "Feuchigkeitssensoren Umbenennen")); humidityRow.AddNewLine(); #region Sync Server HumidityList with Storage foreach (string humiditySensor in PageStorage <HumiditySensorData> .Instance.StorageData.HumiditySensors) { if (settingsData.StorageData.HumiditySensors.ContainsKey(humiditySensor) == false) { settingsData.StorageData.HumiditySensors.Add(humiditySensor, humiditySensor); } } List <string> removeList = new List <string>(); foreach ((string realSensorName, string _) in settingsData.StorageData.HumiditySensors) { if (PageStorage <HumiditySensorData> .Instance.StorageData.HumiditySensors.Contains(realSensorName) == false) { removeList.Add(realSensorName); } } foreach (string s in removeList) { settingsData.StorageData.HumiditySensors.Remove(s); } #endregion Sync Server HumidityList with Storage _humidityDropdown = new Dropdown(new Button(StylingColor.Secondary, true, widthInPx: 150)); humidityRow.AppendCollum(_humidityDropdown, autoSize: true); foreach (string humiditySensor in PageStorage <HumiditySensorData> .Instance.StorageData.HumiditySensors) { StylableAnchor stylableAnchor = _humidityDropdown.AddEntry(humiditySensor); stylableAnchor.Click += (sender, args) => SelectHumiditySensor(humiditySensor); } _humiditySensorTextInputGroup = new TextInputGroup("Freundlicher Name", "Bitte Eingeben!"); humidityRow.AppendCollum(_humiditySensorTextInputGroup, autoSize: true); Button button = new Button(StylingColor.Success, true, text: "Übernehmen"); button.Click += (sender, args) => { if (_humidityDropdown.Button.Text != "") { _settingsData.StorageData.HumiditySensors[_humidityDropdown.Button.Text] = _humiditySensorTextInputGroup.TextInput.Value; } }; humidityRow.AppendCollum(button, autoSize: true); if (PageStorage <HumiditySensorData> .Instance.StorageData.HumiditySensors.Count > 0) { SelectHumiditySensor(PageStorage <HumiditySensorData> .Instance.StorageData.HumiditySensors.First()); } else { humidityRow.IsHidden = true; } humidityRow.AddStyling(StylingOption.MarginBottom, 2); #endregion Rename HumiditySensors #region Backend Server Path grid.AddRow().AppendCollum(new Heading(3, "Backend Server Schnittstelle einstellen") { ClassName = "text-center mb-4" }); Row backendServerRow = grid.AddRow(); Row backendServerConfigurationSingeApiRow = grid.AddRow(); Row backendServerConfigurationMultiApiRow = grid.AddRow(); backendServerRow.AddNewLine(); BackendData backendInstanceStorageData = PageStorage <BackendData> .Instance.StorageData; MultiInputGroup backendConfigurationSourceSwitchingMultiInputGroup = backendServerRow.AppendCollum(new MultiInputGroup()); backendConfigurationSourceSwitchingMultiInputGroup.AppendLabel("Quelle Auswählen", labelSize); TwoStateButtonGroup backendConfigurationSourceSwitchingTwoStateButton = backendConfigurationSourceSwitchingMultiInputGroup.AppendCustomElement(new TwoStateButtonGroup("Sammelkonfiguration", "einzele Konfiguration", !backendInstanceStorageData.SingleApiConfiguration, backendInstanceStorageData.SingleApiConfiguration), false); void OnBackendConfigurationSourceSwitchingTwoStateButtonOnFirstButtonStateChange(object sender, ButtonChangeEventHandlerArgs args) { if (args.NewButtonState == true) { backendServerConfigurationSingeApiRow.Style.Display = "none"; backendServerConfigurationMultiApiRow.Style.Display = null; } else { backendServerConfigurationSingeApiRow.Style.Display = null; backendServerConfigurationMultiApiRow.Style.Display = "none"; } backendInstanceStorageData.SingleApiConfiguration = !args.NewButtonState; } backendConfigurationSourceSwitchingTwoStateButton.FirstButtonStateChange += OnBackendConfigurationSourceSwitchingTwoStateButtonOnFirstButtonStateChange; OnBackendConfigurationSourceSwitchingTwoStateButtonOnFirstButtonStateChange(null, new ButtonChangeEventHandlerArgs(false, !backendInstanceStorageData.SingleApiConfiguration)); backendConfigurationSourceSwitchingMultiInputGroup.AddStyling(StylingOption.MarginBottom, 5); #region backendServerConfigurationSingeApiRow foreach ((string name, BackendProperty backedProperties) in backendInstanceStorageData.BackendProperties) { backendServerConfigurationSingeApiRow.AddNewLine(); backendServerConfigurationSingeApiRow.AppendCollum(CreateSingleBackendCollum(name, backedProperties), autoSize: true); } backendServerConfigurationSingeApiRow.AddNewLine(); backendServerConfigurationSingeApiRow.AddNewLine(); backendServerConfigurationSingeApiRow.AppendCollum(new Button(StylingColor.Light, false, Button.ButtonSize.Normal, false, "Standardkonfiguration eintragen")).Click += (sender, args) => { foreach ((string name, BackendProperty _) in backendInstanceStorageData.BackendProperties) { if (_backendPathTextInputDictionary[name].Value == "") { _backendPathTextInputDictionary[name].Value = $"http://{Dns.GetHostAddresses("WebPiServer.PiWeb")[0].ToString()}:5000/api/{name}"; } } }; #endregion backendServerConfigurationSingeApiRow #region backendServerConfigurationMultiApiRow backendServerConfigurationMultiApiRow.AppendCollum(CreateMultiBackendCollum(backendInstanceStorageData, out StylableTextInput backendServerConfigurationMultiApiTextInput), autoSize: true); backendServerConfigurationMultiApiRow.AddNewLine(); backendServerConfigurationMultiApiRow.AppendCollum(new Button(StylingColor.Light, false, Button.ButtonSize.Normal, false, "Standardkonfiguration eintragen")).Click += (sender, args) => { if (backendServerConfigurationMultiApiTextInput.Value == "") { backendServerConfigurationMultiApiTextInput.Value = $"http://{Dns.GetHostAddresses("WebPiServer.PiWeb")[0].ToString()}:5000/api"; } }; #endregion backendServerConfigurationMultiApiRow #endregion Backend Server Path }
/// <summary> /// Inserts a new key-value pair to this <see cref="BTree{TKey, TValue}"/>, or optionally updates an existing /// one. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="updateIfExists">If this <see cref="BTree{TKey, TValue}"/> already contains a key-value pair /// with the specified <paramref name="key"/>, should it be updated?</param> /// <param name="alreadyExists">Assigned to true if the <paramref name="key"/> was already present in this /// <see cref="BTree{TKey, TValue}"/>, otherwise false.</param> /// <returns>True if any change was made, otherwise false. False indicates that the insertion was rejected /// because the <paramref name="key"/> is already stored in this <see cref="BTree{TKey, TValue}"/> while /// <paramref name="updateIfExists"/> is false, or the insertion failed due to an allocation failure /// (when <see cref="IPageStorage.TryAllocatePage(out long)"/> returns false).</returns> /// <remarks> /// <para> /// This method may split any <see cref="BTreeNode{TKey, TValue}"/>s that are discovered to be at /// full capacity (<see cref="BTreeNode{TKey, TValue}.MaxKeyValuePairCapacity"/>) [often called /// 'preemptive split' or 'proactive insertion']. Even if false is returned (due to insertion /// rejection, or allocation failure), some <see cref="BTreeNode{TKey, TValue}"/>s may have been /// split. This will <em>not</em> have any effect on the correctness of the /// <see cref="BTree{TKey, TValue}"/> or any data that is stored in it. When false is returned, the /// caller can be confident that all stored key-value pairs are unchanged, though they may have /// internally moved between <see cref="BTreeNode{TKey, TValue}"/>s (a result of splitting). /// </para> /// <para> /// Insertion may sometimes require a new <see cref="BTreeNode{TKey, TValue}"/> to be allocated on the /// <see cref="PageStorage"/>. If the <see cref="PageStorage"/> is at full capacity (<see cref="IPageStorage.PageCapacity"/>), /// then inflation may be required to insert a new key-value pair. This method will automatically try to inflate /// the <see cref="PageStorage"/> by one page when necessary (unless <see cref="IPageStorage.IsCapacityFixed"/> /// is true) via the <see cref="IPageStorage.TryInflate(long, IProgress{ProgressReport}, CancellationToken)"/> method. /// If allocation or inflation fails (or <see cref="IPageStorage.IsCapacityFixed"/> is true when inflation is /// necessary), then it may not be possible to insert certain <em>new</em> key-value pairs (depending on the /// value of the <paramref name="key"/> and the current structure of the B-Tree). However, even if inflation /// or allocation fails, it will be possible to update the value associated to an <em>existing</em> /// <paramref name="key"/>. /// </para> /// <para> /// If any <see cref="Exception"/> is thrown (except the <see cref="InvalidOperationException"/> mentioned /// in this document), then the application should assume that data may have been corrupted. /// </para> /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <see cref="IsReadOnly"/> is true or if this method /// was called from within a <see cref="Traverse(bool)"/> enumeration.</exception> public bool Insert(TKey key, TValue value, bool updateIfExists, out bool alreadyExists) { if (IsReadOnly) { throw new InvalidOperationException("Cannot insert to a read-only " + nameof(BTree <TKey, TValue>) + "."); } lock (locker) { if (isTraversing) { throw new InvalidOperationException("Cannot insert key-value pairs to a " + nameof(BTreeNode <TKey, TValue>) + " while traversing it."); } var rootNode = Root; if (rootNode == null) { alreadyExists = false;//The tree is empty, so the key certainly does not already exist if (BTreeNode <TKey, TValue> .TryCreateNew(this, true, out var newRootNode)) { newRootNode.KeyValuePairCount = 1; newRootNode.SetKeyAt(0, key); newRootNode.SetValueAt(0, value); Root = newRootNode; Count++; return(true); } else { //Failed to allocate the root node return(false); } } else if (rootNode.KeyValuePairCount == rootNode.MaxKeyValuePairCapacity) { //The root node is full, so we will split it now if (BTreeNode <TKey, TValue> .TryCreateNew(this, false, out var newRootNode)) //Allocate a new root node { if (BTreeNode <TKey, TValue> .TryCreateNew(this, false, out var splitUsingNode)) //Allocate the 'right' part of the split node { newRootNode.KeyValuePairCount = 1; //Just to allow the split newRootNode.SetSubTreeAt(1, null); //Temporary, just to allow the split [otherwise sub tree at 1 will be undefined, very dangerous!] newRootNode.SetSubTreeAt(0, rootNode); newRootNode.SplitSubTreeAt(0, splitUsingNode); newRootNode.KeyValuePairCount--;//Restore to 'correct' //Now 'newRootNode' has only one KeyValuePair (and two sub-trees, one left, one right) //Determine whether we will insert the new key-value pair to the left or the right sub-tree long dstSubTreeIndex = 0; if (newRootNode.GetKeyAt(0).CompareTo(key) < 0) { dstSubTreeIndex = 1; } Root = newRootNode; if (newRootNode.GetSubTreeAt(dstSubTreeIndex).Insert(key, value, updateIfExists, out alreadyExists)) { if (!alreadyExists) { Count++; } return(true); } else { return(false); } } else { //Free 'newRootNode', since we failed to use it PageStorage.FreePage(newRootNode.PageIndex); //Since allocation failed, we cannot insert a new key-value pair. //But we can still update the value of an existing key-value pair, so don't return yet! } } else { //Failed to allocate a new root node, so we cannot insert a new key-value pair. //But we can still update the value of an existing key-value pair, so don't return yet! } //If we made it here, insertion of a new key-value pair failed. if (updateIfExists) { //Try to update the value of the existing key-value pair (if it exists) if (TryUpdateValue(key, value)) { alreadyExists = true; return(true); } else { //Does not exist, and insertion failed due to allocation failure alreadyExists = false; return(false); } } else { //We are not allowed to update any existing key-value pair, so insertion has failed. //But we still need to let the caller know whether the key already exists. alreadyExists = ContainsKey(key, new CancellationToken(false)); return(false); } } else { //Insert starting from the root if (rootNode.Insert(key, value, updateIfExists, out alreadyExists)) { if (!alreadyExists) { Count++; } return(true); } else { return(false); } } } }
public void ThenUserShouldRedirectedToDesiredPage() { WaitHelper.WaitUntil(() => PageStorage.GetPage <RegimentsAndKitsPage>().RegimentsAndKits_Heading.Displayed); //Assert.IsTrue(PageStorage.GetPage<RegimentsAndKitsPage>().RegimentsAndKits_Heading.Displayed); }
public void WhenUserClickOnRegimentsAndKitSub_LinkOfShopProductsLink() { PageStorage.GetPage <HomePage>().Sub_Menu_Regimens_and_Kits_Link.Click(); }
public void GivenUserIsPresentOnHomePage() { WaitHelper.WaitUntil(() => PageStorage.GetPage <HomePage>().HomePageDisplay.Displayed); }
public void ThenHomePageShouldDisplay() { Assert.IsTrue(PageStorage.GetPage <HomePage>().HomePageTitle.Displayed); }
public void GivenIOpenHomePage() { WaitHelper.WaitUntil(() => PageStorage.GetPage <HomePage>().HomePageDisplay.Displayed); }
private static bool ShowPostById(NameValueCollection args) { try { if (string.IsNullOrEmpty(SettingsManager.PersistentSettings.CurrentUser.Login)) { return(false); } var idArg = args.Get("id"); if (string.IsNullOrEmpty(idArg)) { return(false); } if (!int.TryParse(idArg, out var id)) { return(false); } if (id < 0) { return(false); } var result = MainWindow.Instance.Dispatcher.Invoke(() => { if (!NavigationController.Instance.IsCurrentPage <FeedPage>()) { NavigationController.Instance.RequestPage <FeedPage>( null, true); } Post sourcePost = null; var page = (FeedPage)PageStorage.GetPage <FeedPage>(); if (page.PostsTypesComboBox.SelectedItem == null) { return(false); } var postType = ((KeyValuePair <PostType, string>)page.PostsTypesComboBox.SelectedItem) .Key; switch (postType) { case PostType.Popular: if (page.PostsWrapPanel.Children.Count == 0) { break; } foreach (var element in page.PostsWrapPanel.Children) { if (!(element is Post post)) { continue; } if (post.CurrentPostData.Id != id) { continue; } sourcePost = post; break; } break; case PostType.New: case PostType.My: case PostType.Favorite: if (page.PostsWrapPanel.Children.Count == 0) { break; } if (page.PostsWrapPanel.Children.Count > 2 && (page.PostsWrapPanel.Children[0] is Post startPost && page.PostsWrapPanel.Children[^ 1] is Post endPost) && !(startPost.CurrentPostData.Id >= id && id >= endPost.CurrentPostData.Id)) { break; } foreach (var element in page.PostsWrapPanel.Children) { if (!(element is Post post)) { continue; } if (post.CurrentPostData.Id != id) { continue; } sourcePost = post; break; } break; default: break; } NavigationController.Instance.RequestOverlay <PostOverlayPage>(new PostOverlayViewModel { SourcePost = sourcePost, CurrentPostData = new PostSchema { Id = id } }); return(true); }); return(result); } catch (Exception ex) { var method = MethodBase.GetCurrentMethod(); ProtocolSchemaUtils.LogApiMethodError( ex, method, StaticSchemaName, StaticVersion, args); return(false); } }