Ejemplo n.º 1
0
        /// <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);
            }
        }
Ejemplo n.º 2
0
        /// <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
            }
        }
Ejemplo n.º 3
0
        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"));
        }
Ejemplo n.º 4
0
        /// <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;
                }
            }
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
            }
        }
Ejemplo n.º 8
0
        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();
        }
Ejemplo n.º 9
0
        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);
            }
        }
Ejemplo n.º 10
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
            }
        }
Ejemplo n.º 11
0
        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();
        }
Ejemplo n.º 12
0
        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");
        }
Ejemplo n.º 13
0
        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);
                }
            }
        }
Ejemplo n.º 14
0
        /// <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);
            }
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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");
        }
Ejemplo n.º 17
0
        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
        }
Ejemplo n.º 18
0
        /// <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);
                    }
                }
            }
        }
Ejemplo n.º 19
0
 public void ThenUserShouldRedirectedToDesiredPage()
 {
     WaitHelper.WaitUntil(() => PageStorage.GetPage <RegimentsAndKitsPage>().RegimentsAndKits_Heading.Displayed);
     //Assert.IsTrue(PageStorage.GetPage<RegimentsAndKitsPage>().RegimentsAndKits_Heading.Displayed);
 }
Ejemplo n.º 20
0
 public void WhenUserClickOnRegimentsAndKitSub_LinkOfShopProductsLink()
 {
     PageStorage.GetPage <HomePage>().Sub_Menu_Regimens_and_Kits_Link.Click();
 }
Ejemplo n.º 21
0
 public void GivenUserIsPresentOnHomePage()
 {
     WaitHelper.WaitUntil(() => PageStorage.GetPage <HomePage>().HomePageDisplay.Displayed);
 }
Ejemplo n.º 22
0
 public void ThenHomePageShouldDisplay()
 {
     Assert.IsTrue(PageStorage.GetPage <HomePage>().HomePageTitle.Displayed);
 }
Ejemplo n.º 23
0
 public void GivenIOpenHomePage()
 {
     WaitHelper.WaitUntil(() => PageStorage.GetPage <HomePage>().HomePageDisplay.Displayed);
 }
Ejemplo n.º 24
0
        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);
            }
        }