public void SinglePage(int pageSize)
        {
            var fsManager = new FileSystemPageManager(pageSize);
            var manager   = new CachingPageManager(fsManager, 100, 100);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                // append a page
                IPage page = manager.CreatePage();

                // fill and update it
                var r = new Random();
                r.NextBytes(page.Content);
                manager.UpdatePage(page);

                // fetch updated content
                IPage fetchedPage = manager.FetchPage(page.Index);
                Assert.IsTrue(AreEqualByteArrays(page.Content, fetchedPage.Content));

                // remove it
                manager.RemovePage(page.Index);

                // try to fetch removed page
                Assert.Throws <PageMapException>(() => manager.FetchPage(page.Index));

                // resurrect and check content
                page = manager.CreatePage();
                Assert.IsTrue(AreEqualByteArrays(new byte[manager.PageSize], page.Content));
            }
        }
Пример #2
0
        public void FixedSizeItemsLength()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var fsm = new FreeSpaceMap(manager);

                var memoryManager = new MemoryManager(fsm, manager);

                int count = 1000;

                var items = new Dictionary <DbItemReference, byte[]>();

                var r = new Random();

                // allocate items
                for (int i = 0; i < count; i++)
                {
                    var sizeRange = GetRandomFixedSizeItemsSizeRange();
                    var content   = GenerateRandomSequence(DbItem.GetMaxSize(sizeRange) - r.Next(5));
                    var reference = memoryManager.Allocate(content);
                    items[reference] = content;
                }

                // check lengths
                foreach (var reference in items.Keys)
                {
                    Assert.AreEqual(items[reference].Length, memoryManager.GetLength(reference));
                }
            }
        }
Пример #3
0
        public void MultiPage(int pageSize)
        {
            var manager = new FileSystemPageManager(pageSize);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var r = new Random();

                // fill storage with random data
                int pageCount = 1000;
                var pages     = new IPage[pageCount];
                for (int i = 0; i < pageCount; i++)
                {
                    pages[i] = manager.CreatePage();
                    r.NextBytes(pages[i].Content);
                    manager.UpdatePage(pages[i]);
                }

                // fetch and compare pages
                CheckStoragePages(pages, manager);

                // generate a random indexes
                int k = 0;
                var indexesToDelete = new long[pageCount / 2];
                while (k < pageCount / 2)
                {
                    int index = r.Next(pageCount);
                    if (!indexesToDelete.Contains(index))
                    {
                        indexesToDelete[k] = index;
                        k++;
                    }
                }

                // remove pages with these indexes
                foreach (long i in indexesToDelete)
                {
                    manager.RemovePage(i);
                }

                // fetch and compare pages
                CheckStoragePages(pages, manager, indexesToDelete);

                // add more pages
                for (int i = 0; i < pageCount; i++)
                {
                    if (indexesToDelete.Contains(pages[i].Index))
                    {
                        pages[i] = manager.CreatePage();
                        r.NextBytes(pages[i].Content);
                        manager.UpdatePage(pages[i]);
                    }
                }

                // check again
                CheckStoragePages(pages, manager);
            }
        }
Пример #4
0
        public void InsertVariableSizeItemAfterDelete()
        {
            int pageSize         = 4096;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var header = new RadixTreeNodesPageHeader
            {
                FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length)
            };

            PageFormatter.InitPage(p, header);

            var r = new Random();

            var items = new List <byte[]>();

            var item = new byte[r.Next(100) + 1];

            r.NextBytes(item);

            short itemIndex = 0;

            while (itemIndex != -1)
            {
                itemIndex = PageFormatter.AddVariableSizeItem(p, item);
                items.Add(item);

                item = new byte[r.Next(100) + 1];
                r.NextBytes(item);
            }

            bool hasRemainingItems;

            // replace with the same
            PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems);
            Assert.AreEqual(1, PageFormatter.AddVariableSizeItem(p, items[1]));

            item = PageFormatter.ReadVariableSizeItem(p, 1);
            Assert.IsTrue(AreEqualByteArrays(items[1], item));

            // replace with smaller one
            PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems);
            var smallItem = new byte[items[1].Length / 2 + 1];

            r.NextBytes(smallItem);
            Assert.AreEqual(1, PageFormatter.AddVariableSizeItem(p, smallItem));

            item = PageFormatter.ReadVariableSizeItem(p, 1);
            Assert.IsTrue(AreEqualByteArrays(smallItem, item));

            // and put original again
            PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems);
            PageFormatter.AddVariableSizeItem(p, items[1]);

            item = PageFormatter.ReadVariableSizeItem(p, 1);
            Assert.IsTrue(AreEqualByteArrays(items[1], item));
        }
Пример #5
0
        public void FixedSizeItemsAllocation()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var fsm = new FreeSpaceMap(manager);

                var memoryManager = new MemoryManager(fsm, manager);

                int count = 100000;

                var items = new Dictionary <DbItemReference, byte[]>();

                // allocate items
                for (int i = 0; i < count; i++)
                {
                    var sizeRange = GetRandomFixedSizeItemsSizeRange();
                    var content   = GenerateRandomSequence(DbItem.GetMaxSize(sizeRange));
                    var reference = memoryManager.Allocate(content);
                    items[reference] = content;
                }

                // check contents
                foreach (var reference in items.Keys)
                {
                    Assert.IsTrue(AreEqualByteArrays(items[reference], memoryManager.Get(reference).RawData));
                }

                // free half of the items
                var freedItems = new Dictionary <DbItemReference, byte[]>();

                foreach (var reference in items.Keys)
                {
                    if (_r.NextDouble() > 0.5)
                    {
                        memoryManager.Free(reference);
                        freedItems[reference] = items[reference];
                    }
                }

                // check that the items do not exist
                foreach (var reference in freedItems.Keys)
                {
                    Assert.IsNull(memoryManager.Get(reference));
                }

                // and the remaining items still available
                foreach (var reference in items.Keys.Where(item => !freedItems.ContainsKey(item)))
                {
                    Assert.IsTrue(AreEqualByteArrays(items[reference], memoryManager.Get(reference).RawData));
                }
            }
        }
Пример #6
0
        public void ShouldSuccessfulyCreateFsm()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                new FreeSpaceMap(manager);
            }
        }
Пример #7
0
        /// <summary>
        /// Initializes a new instance of the RecoveryFile
        /// </summary>
        /// <param name="pageManager"></param>
        /// <param name="pageSize"></param>
        public RecoveryFile(FileSystemPageManager pageManager, int pageSize)
        {
            if (pageManager == null)
            {
                throw new ArgumentNullException(nameof(pageManager));
            }


            _pageManager = pageManager;
            _pageSize    = pageSize;
        }
Пример #8
0
        public void ConcurrentAccess()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                _sharedManager = manager;

                // create threads
                var threads = new List <Thread>();
                for (int i = 0; i < 5; i++)
                {
                    threads.Add(new Thread(AddPagesRoutine));
                }

                // and start them
                foreach (Thread thread in threads)
                {
                    thread.Start();
                }

                // wait for end of work
                foreach (Thread thread in threads)
                {
                    thread.Join();
                }

                // fetch and compare pages
                CheckStoragePages(_sharedPages, manager);

                threads.Clear();

                // run the same test for random operations
                for (int i = 0; i < 5; i++)
                {
                    threads.Add(new Thread(RandomOperationsRoutine));
                }

                foreach (Thread thread in threads)
                {
                    thread.Start();
                }

                foreach (Thread thread in threads)
                {
                    thread.Join();
                }

                CheckStoragePages(_sharedPages, manager);
            }
        }
Пример #9
0
        public void PageHasNoRemainingItemsAfterDelete()
        {
            int pageSize         = 4096;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var header = new RadixTreeNodesPageHeader
            {
                FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length)
            };

            PageFormatter.InitPage(p, header);

            var r = new Random();

            var items = new List <byte[]>();

            var item = new byte[r.Next(100) + 1];

            r.NextBytes(item);

            short itemIndex = 0;

            while (itemIndex != -1)
            {
                itemIndex = PageFormatter.AddVariableSizeItem(p, item);
                if (itemIndex == -1)
                {
                    continue;
                }

                items.Add(item);

                item = new byte[r.Next(100) + 1];
                r.NextBytes(item);
            }

            bool hasRemainingItems;

            for (short i = 0; i < items.Count; i++)
            {
                PageFormatter.DeleteVariableSizeItem(p, i, out hasRemainingItems);
                if (i < items.Count - 1)
                {
                    Assert.IsTrue(hasRemainingItems);
                }
                else
                {
                    Assert.IsFalse(hasRemainingItems);
                }
            }
        }
Пример #10
0
        public void RandomAccess()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var r = new Random();

                // fill storage with random data
                int pageCount = 1000;
                var pages     = new List <IPage>();
                for (int i = 0; i < pageCount; i++)
                {
                    pages.Add(manager.CreatePage());
                    r.NextBytes(pages[i].Content);
                    manager.UpdatePage(pages[i]);
                }

                int operationCount = 1000;
                for (int k = 0; k < operationCount; k++)
                {
                    int op = r.Next(3);
                    switch (op)
                    {
                    case 0:     // update
                        int index = r.Next(pages.Count - 1);
                        r.NextBytes(pages[index].Content);
                        manager.UpdatePage(pages[index]);
                        break;

                    case 1:     // add
                        IPage page = manager.CreatePage();
                        r.NextBytes(page.Content);
                        manager.UpdatePage(page);
                        pages.Add(page);
                        break;

                    case 2:     // remove
                        index = r.Next(pages.Count - 1);
                        manager.RemovePage(pages[index].Index);
                        pages.RemoveAt(index);
                        break;
                    }
                }

                // fetch and compare pages
                CheckStoragePages(pages, manager);
            }
        }
Пример #11
0
        public void CorrectlyRecoverSequentiallyUpdatedPage()
        {
            long index;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                {
                    storage.OpenOrCreate(StoragePath);
                    var page = fileSystemPageManager.CreatePage();
                    index = page.Index;
                }

            string fileName;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                    using (var recoveryFile = new RecoveryFile(fileSystemPageManager, fileSystemPageManager.PageSize))
                    {
                        storage.OpenOrCreate(StoragePath);
                        var page = fileSystemPageManager.FetchPage(index);
                        index = page.Index;
                        fileSystemPageManager.Dispose();

                        Assert.AreEqual(index, page.Index);
                        Assert.AreNotEqual(0xff, page.Content[10]);

                        // Update twice with different bytes to make sure the latest one wins
                        page.Content[9]  = 0xaa;
                        page.Content[10] = 0xaa;
                        recoveryFile.WriteUpdatePageRecord(page);
                        page.Content[10] = 0xff;
                        recoveryFile.WriteUpdatePageRecord(page);

                        recoveryFile.WriteFinalMarker();
                        fileName = recoveryFile.FileName;
                    }

            Assert.True(File.Exists(fileName));
            Assert.GreaterOrEqual(new FileInfo(fileName).Length, 1);
            Assert.AreNotEqual(index, 0);

            using (var manager = new FileSystemPageManager(4096))
                using (var storage = new Storage(manager))
                {
                    storage.OpenOrCreate(StoragePath);
                    var page = manager.FetchPage(index);
                    Assert.AreEqual(index, page.Index);
                    Assert.AreEqual(0xaa, page.Content[9]);
                    Assert.AreEqual(0xff, page.Content[10]);
                }
        }
Пример #12
0
        public void FixedSizeItemsPage()
        {
            int pageSize         = 32768;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var header = new FixedSizeItemsPageHeader();
            var r      = new Random();

            foreach (var sizeRange in EnumHelper.FixedSizeItemsSizeRanges())
            {
                header.SizeRange = sizeRange;

                PageFormatter.InitPage(p, header);

                var item = new DbItem(new byte[DbItem.GetMaxSize(header.SizeRange)]);
                r.NextBytes(item.RawData);

                // fill the page with the items
                short count        = 0;
                bool  spaceRemains = true;
                while (PageFormatter.HasFreeSpaceForFixedSizeItem(p))
                {
                    Assert.IsTrue(spaceRemains);
                    PageFormatter.AddFixedSizeItem(p, item, out spaceRemains);
                    count++;
                    Assert.AreEqual(count, PageFormatter.ReadFixedSizeItemsCount(p));
                }

                Assert.IsFalse(spaceRemains);

                // check if fetched objects are equal to originals
                for (short j = 0; j < PageFormatter.ReadFixedSizeItemsCount(p); j++)
                {
                    DbItem readItem = PageFormatter.ReadFixedSizeItem(p, j);
                    Assert.IsTrue(AreEqualByteArrays(item.RawData, readItem.RawData));
                }

                // delete all added items
                short itemindex = 0;
                while (PageFormatter.ReadFixedSizeItemsCount(p) > 0)
                {
                    PageFormatter.DeleteFixedSizeItem(p, itemindex);
                    count--;
                    itemindex++;
                    Assert.AreEqual(count, PageFormatter.ReadFixedSizeItemsCount(p));
                }
            }
        }
Пример #13
0
        public void OnEmptyStorageShouldReturnMinusOneForRequestedFreePageIndex()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                var fsm = new FreeSpaceMap(manager);

                foreach (var fsmValue in EnumHelper.FixedSizeItemsFsmValues())
                {
                    Assert.AreEqual(-1, fsm.GetFreePageIndex(fsmValue));
                }
            }
        }
Пример #14
0
        public void OnEmptyStorageAllRequestedPagesShouldBeFull()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                var fsm = new FreeSpaceMap(manager);

                int entryCount = PageFormatter.GetFsmEntryCount(manager.FetchPage(1));

                for (int i = 0; i < entryCount; i++)
                {
                    Assert.AreEqual(FsmValue.Full, fsm.Get(i));
                }
            }
        }
Пример #15
0
        public void ReadVariableSizeItems()
        {
            int pageSize         = 4096;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var header = new RadixTreeNodesPageHeader
            {
                FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length)
            };

            PageFormatter.InitPage(p, header);

            var r = new Random();

            var items = new List <byte[]>();

            var item = new byte[r.Next(100) + 1];

            r.NextBytes(item);

            while (PageFormatter.AddVariableSizeItem(p, item) != -1)
            {
                items.Add(item);

                item = new byte[r.Next(100) + 1];
                r.NextBytes(item);
            }

            for (short i = 0; i < items.Count; i++)
            {
                item = PageFormatter.ReadVariableSizeItem(p, i);
                Assert.IsTrue(AreEqualByteArrays(items[i], item));
            }

            bool hasRemainingItems;

            PageFormatter.DeleteVariableSizeItem(p, 0, out hasRemainingItems);
            PageFormatter.DeleteVariableSizeItem(p, 2, out hasRemainingItems);
            PageFormatter.DeleteVariableSizeItem(p, (short)(items.Count - 1), out hasRemainingItems);

            Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, 0));
            Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, 2));
            Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, (short)(items.Count - 1)));
        }
Пример #16
0
        public void CorrectlyApplyDeleteRecord()
        {
            long deleteIndex;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                {
                    storage.OpenOrCreate(StoragePath);
                    deleteIndex = fileSystemPageManager.CreatePage().Index;
                }

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                {
                    storage.OpenOrCreate(StoragePath);
                    Assert.True(fileSystemPageManager.PageExists(deleteIndex));
                }

            string fileName;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                    using (var recoveryFile = new RecoveryFile(fileSystemPageManager, fileSystemPageManager.PageSize))
                    {
                        storage.OpenOrCreate(StoragePath);
                        fileSystemPageManager.Dispose();

                        recoveryFile.WriteDeletePageRecord(deleteIndex);

                        recoveryFile.WriteFinalMarker();
                        fileName = recoveryFile.FileName;
                    }

            Assert.True(File.Exists(fileName));
            Assert.GreaterOrEqual(new FileInfo(fileName).Length, 1);

            using (var manager = new FileSystemPageManager(4096))
                using (var storage = new Storage(manager))
                {
                    storage.OpenOrCreate(StoragePath);
                    Assert.False(manager.PageExists(deleteIndex));
                    Assert.AreEqual(deleteIndex, manager.CreatePage().Index);
                }
        }
Пример #17
0
        public void SinglePage(int pageSize)
        {
            var manager = new FileSystemPageManager(pageSize);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                // append a page
                IPage page = manager.CreatePage();

                // fill and update it
                var r = new Random();
                r.NextBytes(page.Content);
                manager.UpdatePage(page);

                // fetch updated content
                IPage fetchedPage = manager.FetchPage(page.Index);
                Assert.IsTrue(AreEqualByteArrays(page.Content, fetchedPage.Content));

                // remove it
                manager.RemovePage(page.Index);
                bool exceptionThrown = false;

                // try to fetch removed page
                try
                {
                    manager.FetchPage(page.Index);
                }
                catch (PageMapException)
                {
                    exceptionThrown = true;
                }

                if (!exceptionThrown)
                {
                    Assert.Fail("Exception was not thrown");
                }

                // resurrect and check content
                page = manager.CreatePage();
                Assert.IsTrue(AreEqualByteArrays(new byte[manager.PageSize], page.Content));
            }
        }
Пример #18
0
        public void MultiPageOperations()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                var fsm = new FreeSpaceMap(manager);

                int entryPerPage = PageFormatter.GetFsmEntryCount(manager.FetchPage(1));
                int entryCount   = entryPerPage * 3;

                // check writing to the last page
                var value = FsmValue.Class0;
                var index = entryCount - 1;
                fsm.Set(index, value);
                Assert.AreEqual(value, fsm.Get(index));

                // middle page
                value = FsmValue.Class1;
                index = entryPerPage + 1;
                fsm.Set(index, value);
                Assert.AreEqual(value, fsm.Get(index));

                // the first page
                value = FsmValue.Class2;
                index = entryPerPage - 1;
                fsm.Set(index, value);
                Assert.AreEqual(value, fsm.Get(index));

                for (int i = 0; i < entryCount; i++)
                {
                    fsm.Set(i, FsmValue.Class3);
                }

                for (int i = 0; i < entryCount; i++)
                {
                    long pageIndex = fsm.GetFreePageIndex(FsmValue.Class3);
                    Assert.AreNotEqual(-1, pageIndex);
                    fsm.Set(i, FsmValue.Full);
                }
            }
        }
Пример #19
0
        public void MultipageItemSegments()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);

                var fsm = new FreeSpaceMap(manager);

                var memoryManager = new MemoryManager(fsm, manager);

                var             content   = GenerateRandomSequence(4096 * 5 + 100);
                DbItemReference reference = memoryManager.Allocate(content);

                // check full content
                Assert.IsTrue(AreEqualByteArrays(content, memoryManager.GetItemSegment(reference, 0, content.Length - 1)));

                var bytes = new byte[2];

                // check first two bytes
                Array.Copy(content, 0, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 0, 1)));

                // check next two bytes
                Array.Copy(content, 2, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 2, 3)));

                // check last two bytes
                Array.Copy(content, content.Length - 2, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, content.Length - 2, content.Length - 1)));

                //last but two bytes
                Array.Copy(content, content.Length - 4, bytes, 0, 2);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, content.Length - 4, content.Length - 3)));

                //all except first two bytes and last two bytes
                bytes = new byte[content.Length - 4];
                Array.Copy(content, 2, bytes, 0, content.Length - 4);
                Assert.IsTrue(AreEqualByteArrays(bytes, memoryManager.GetItemSegment(reference, 2, content.Length - 3)));
            }
        }
Пример #20
0
        private void AddPagesRoutine()
        {
            FileSystemPageManager manager = _sharedManager;

            var r = new Random();

            // fill storage with random data
            int pageCount = 1000;

            for (int i = 0; i < pageCount; i++)
            {
                var page = manager.CreatePage();
                lock (_locker)
                {
                    _sharedPages.Add(page);
                }
                r.NextBytes(page.Content);
                manager.UpdatePage(page);
            }
        }
Пример #21
0
        public void SinglePageOperations()
        {
            var manager = new FileSystemPageManager(4096);

            using (var storage = new Storage(manager))
            {
                storage.CreateNew(StoragePath);
                var fsm = new FreeSpaceMap(manager);

                var r          = new Random();
                int entryCount = PageFormatter.GetFsmEntryCount(manager.FetchPage(1));

                for (int i = 0; i < 100000; i++)
                {
                    var value = (FsmValue)r.Next((int)FsmValue.Max);
                    var index = r.Next(entryCount);
                    fsm.Set(index, value);

                    Assert.AreEqual(value, fsm.Get(index));
                }
            }
        }
Пример #22
0
        public void FsmPage()
        {
            int pageSize         = 32768;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var fsmh = new FreeSpaceMapPageHeader();
            var r    = new Random();

            PageFormatter.InitPage(p, fsmh);
            int fsmEntryCount = PageFormatter.GetFsmEntryCount(p);

            // set all values to "full"
            PageFormatter.SetAllFsmValues(p, FsmValue.Full);

            // check if all values are actually "full"
            for (int i = 0; i < fsmEntryCount; i++)
            {
                Assert.AreEqual(FsmValue.Full, PageFormatter.GetFsmValue(p, i));
            }

            var values = new FsmValue[fsmEntryCount];

            // set and keep random values
            for (int i = 0; i < fsmEntryCount; i++)
            {
                var value = (byte)r.Next((byte)FsmValue.Full + 1);
                PageFormatter.SetFsmValue(p, i, (FsmValue)value);
                values[i] = (FsmValue)value;
            }

            // compare it
            for (int i = 0; i < fsmEntryCount; i++)
            {
                Assert.AreEqual(values[i], PageFormatter.GetFsmValue(p, i));
            }
        }
Пример #23
0
        /// <summary>
        /// Creates a new storage instance with specified types of keys and values.
        /// </summary>
        /// <typeparam name="TKey">The type of key</typeparam>
        /// <typeparam name="TValue">The type of value</typeparam>
        /// <param name="keySerializer">Object implementing ISerializer interface for key serialization</param>
        /// <param name="valueSerializer">Object implementing ISerializer interface for value serialization</param>
        /// <param name="settings">Setiings of creating storage</param>
        /// <returns>New storage instance</returns>
        public IBPlusTreeKeyValueStorage <ComparableKeyOf <TKey>, ValueOf <TValue> > CreateBPlusTreeStorage <TKey, TValue>(ISerializer <TKey> keySerializer,
                                                                                                                           ISerializer <TValue> valueSerializer,
                                                                                                                           BPlusTreeStorageSettings settings)
            where TKey : IComparable
        {
            bool usePageCache = settings.CacheSettings != null;

            if (settings.MaxEmptyPages < 0)
            {
                throw new ArgumentException("MaxEmptyPages shouldn't be negative", nameof(settings));
            }

            if (usePageCache)
            {
                if (settings.CacheSettings.MaxCachedPages < 0)
                {
                    throw new ArgumentException("MaxCachedPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages < 0)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages > settings.CacheSettings.MaxCachedPages)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn be equal to or less than MaxCachedPages", nameof(settings));
                }
            }

            IPageManager pageManager   = null;
            IPageManager fsPageManager = null;

            try
            {
                var asyncWriteBuffer = usePageCache ? Math.Min(settings.CacheSettings.MaxDirtyPages, 1000) : 100;

                fsPageManager = new FileSystemPageManager((int)settings.PageSize, settings.ForcedWrites, asyncWriteBuffer, true)
                {
                    MaxEmptyPages = settings.MaxEmptyPages
                };

                pageManager = usePageCache ?
                              new CachingPageManager(fsPageManager, settings.CacheSettings.MaxCachedPages, settings.CacheSettings.MaxDirtyPages)
                                : fsPageManager;

                var ks = new Serializer <ComparableKeyOf <TKey> >(obj => keySerializer.Serialize(obj), bytes => keySerializer.Deserialize(bytes));
                var vs = new Serializer <ValueOf <TValue> >(obj => valueSerializer.Serialize(obj), bytes => valueSerializer.Deserialize(bytes));

                if (settings.MaxKeySize <= 0)
                {
                    throw new ArgumentException("MaxKeySize size should be positive", nameof(settings));
                }

                var bPlusTree = new BPlusTree <ComparableKeyOf <TKey>, ValueOf <TValue> >(
                    new BPlusTreeNodeStorage <ComparableKeyOf <TKey> >(pageManager, ks, settings.MaxKeySize),
                    new ValueStorage <ValueOf <TValue> >(new MemoryManager(new FreeSpaceMap(pageManager), pageManager), vs));

                return(new BPlusTreeKeyValueStorage <ComparableKeyOf <TKey>, ValueOf <TValue> >(pageManager, bPlusTree, settings.MaxKeySize, settings.AutoFlushInterval, settings.AutoFlushTimeout));
            }
            catch (Exception)
            {
                if (pageManager != null)
                {
                    pageManager.Close();
                }
                else
                {
                    fsPageManager?.Close();
                }

                throw;
            }
        }
Пример #24
0
        public void CorrectWriteAndReadAllHeaders()
        {
            int pageSize         = 4096;
            var dummyPageManager = new FileSystemPageManager(pageSize);
            var p = new Page(dummyPageManager, 0, new byte[pageSize]);

            var hph = new HeadingPageHeader();

            PageFormatter.InitPage(p, hph);
            PageHeaderBase phb = PageFormatter.GetPageHeader(p);

            Assert.IsInstanceOf <HeadingPageHeader>(phb);
            Assert.AreEqual(hph.Length, phb.Length);
            Assert.AreEqual(hph.PageType, phb.PageType);
            Assert.AreEqual(hph.SizeRange, phb.SizeRange);

            var fsiph = new FixedSizeItemsPageHeader();

            PageFormatter.InitPage(p, fsiph);
            phb = PageFormatter.GetPageHeader(p);
            Assert.IsInstanceOf <FixedSizeItemsPageHeader>(phb);
            Assert.AreEqual(fsiph.Length, phb.Length);
            Assert.AreEqual(fsiph.PageType, phb.PageType);
            Assert.AreEqual(fsiph.SizeRange, phb.SizeRange);

            var mpph = new MultipageItemPageHeader();

            PageFormatter.InitPage(p, mpph);
            phb = PageFormatter.GetPageHeader(p);
            Assert.IsInstanceOf <MultipageItemPageHeader>(phb);
            Assert.AreEqual(mpph.Length, phb.Length);
            Assert.AreEqual(mpph.PageType, phb.PageType);
            Assert.AreEqual(mpph.SizeRange, phb.SizeRange);
            Assert.AreEqual(mpph.StartPageIndex, ((MultipageItemPageHeader)phb).StartPageIndex);
            Assert.AreEqual(mpph.PreviousPageIndex, ((MultipageItemPageHeader)phb).PreviousPageIndex);
            Assert.AreEqual(mpph.NextPageIndex, ((MultipageItemPageHeader)phb).NextPageIndex);

            var fsmph = new FreeSpaceMapPageHeader();

            PageFormatter.InitPage(p, fsmph);
            phb = PageFormatter.GetPageHeader(p);
            Assert.IsInstanceOf <FreeSpaceMapPageHeader>(phb);
            Assert.AreEqual(fsmph.Length, phb.Length);
            Assert.AreEqual(fsmph.PageType, phb.PageType);
            Assert.AreEqual(fsmph.SizeRange, phb.SizeRange);
            Assert.AreEqual(fsmph.BasePageIndex, ((FreeSpaceMapPageHeader)phb).BasePageIndex);

            var tnph = new BPlusTreeNodePageHeader();

            PageFormatter.InitPage(p, tnph);
            phb = PageFormatter.GetPageHeader(p);
            Assert.IsInstanceOf <BPlusTreeNodePageHeader>(phb);
            Assert.AreEqual(tnph.Length, phb.Length);
            Assert.AreEqual(tnph.PageType, phb.PageType);
            Assert.AreEqual(tnph.SizeRange, phb.SizeRange);
            Assert.AreEqual(tnph.ParentPageIndex, ((BPlusTreeNodePageHeader)phb).ParentPageIndex);
            Assert.AreEqual(tnph.PreviousPageIndex, ((BPlusTreeNodePageHeader)phb).PreviousPageIndex);
            Assert.AreEqual(tnph.NextPageIndex, ((BPlusTreeNodePageHeader)phb).NextPageIndex);

            var rtnph = new RadixTreeNodesPageHeader();

            PageFormatter.InitPage(p, rtnph);
            phb = PageFormatter.GetPageHeader(p);
            Assert.IsInstanceOf <RadixTreeNodesPageHeader>(phb);
            Assert.AreEqual(rtnph.Length, phb.Length);
            Assert.AreEqual(rtnph.PageType, phb.PageType);
            Assert.AreEqual(rtnph.SizeRange, phb.SizeRange);
            Assert.AreEqual(rtnph.FreeSpace, ((RadixTreeNodesPageHeader)phb).FreeSpace);
        }
Пример #25
0
        /// <summary>
        /// Creates a new storage instance with specified types of keys and values.
        /// </summary>
        /// <typeparam name="TKey">The type of key</typeparam>
        /// <typeparam name="TValue">The type of value</typeparam>
        /// <param name="keySerializer">Object implementing ISerializer interface for key serialization</param>
        /// <param name="valueSerializer">Object implementing ISerializer interface for value serialization</param>
        /// <param name="settings">Setiings of creating storage</param>
        /// <returns>New storage instance</returns>
        public IKeyValueStorage <KeyOf <TKey>, ValueOf <TValue> > CreateRadixTreeStorage <TKey, TValue>(ISerializer <TKey> keySerializer,
                                                                                                        ISerializer <TValue> valueSerializer,
                                                                                                        RadixTreeStorageSettings settings)
        {
            bool usePageCache = settings.CacheSettings != null;

            if (settings.MaxEmptyPages < 0)
            {
                throw new ArgumentException("MaxEmptyPages shouldn't be negative", nameof(settings));
            }

            if (usePageCache)
            {
                if (settings.CacheSettings.MaxCachedPages < 0)
                {
                    throw new ArgumentException("MaxCachedPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages < 0)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn't be negative", nameof(settings));
                }

                if (settings.CacheSettings.MaxDirtyPages > settings.CacheSettings.MaxCachedPages)
                {
                    throw new ArgumentException("MaxDirtyPages shouldn be equal to or less than MaxCachedPages", nameof(settings));
                }
            }

            IPageManager pageManager   = null;
            IPageManager fsPageManager = null;

            try
            {
                fsPageManager = new FileSystemPageManager((int)settings.PageSize, settings.ForcedWrites, 1, true)
                {
                    MaxEmptyPages = settings.MaxEmptyPages
                };

                pageManager = usePageCache ?
                              new CachingPageManager(fsPageManager, settings.CacheSettings.MaxCachedPages, settings.CacheSettings.MaxDirtyPages)
                                : fsPageManager;

                var ks = new Serializer <KeyOf <TKey> >(obj => keySerializer.Serialize(obj), bytes => keySerializer.Deserialize(bytes));
                var vs = new Serializer <ValueOf <TValue> >(obj => valueSerializer.Serialize(obj), bytes => valueSerializer.Deserialize(bytes));

                var radixTree = new RadixTree <KeyOf <TKey>, ValueOf <TValue> >(
                    new RadixTreeNodeStorage(pageManager),
                    new ValueStorage <ValueOf <TValue> >(new MemoryManager(new FreeSpaceMap(pageManager), pageManager), vs), ks);

                return(new RadixTreeKeyValueStorage <KeyOf <TKey>, ValueOf <TValue> >(pageManager, radixTree, settings.AutoFlushInterval, settings.AutoFlushTimeout));
            }
            catch (Exception)
            {
                if (pageManager != null)
                {
                    pageManager.Close();
                }
                else
                {
                    fsPageManager?.Close();
                }

                throw;
            }
        }
Пример #26
0
        public void CorrectlyRecoverResurrectedPage()
        {
            long index;
            long resurrectIndex;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                {
                    storage.OpenOrCreate(StoragePath);
                    var page = fileSystemPageManager.CreatePage();
                    index = page.Index;
                }

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                {
                    storage.OpenOrCreate(StoragePath);
                    var page = fileSystemPageManager.FetchPage(index);
                    Assert.AreEqual(index, page.Index);
                    Assert.AreNotEqual(0xff, page.Content[10]);
                }

            string fileName;

            using (var fileSystemPageManager = new FileSystemPageManager(4096))
                using (var storage = new Storage(fileSystemPageManager))
                    using (var recoveryFile = new RecoveryFile(fileSystemPageManager, fileSystemPageManager.PageSize))
                    {
                        storage.OpenOrCreate(StoragePath);
                        var page = fileSystemPageManager.FetchPage(index);
                        index = page.Index;

                        page.Content[10] = 0xaf;

                        fileSystemPageManager.RemovePage(index);
                        var resurrectedPage = fileSystemPageManager.CreatePage();
                        resurrectIndex = resurrectedPage.Index;

                        //check we're not going wrong way
                        Assert.AreEqual(index, resurrectIndex);

                        resurrectedPage.Content[10] = 0xff;
                        Assert.AreNotEqual(0xff, page.Content[10]);

                        fileSystemPageManager.Dispose();

                        recoveryFile.WriteUpdatePageRecord(page);
                        recoveryFile.WriteDeletePageRecord(index);
                        recoveryFile.WriteUpdatePageRecord(resurrectedPage);

                        recoveryFile.WriteFinalMarker();

                        fileName = recoveryFile.FileName;
                    }

            Assert.True(File.Exists(fileName));
            Assert.GreaterOrEqual(new FileInfo(fileName).Length, 1);

            using (var manager = new FileSystemPageManager(4096))
                using (var storage = new Storage(manager))
                {
                    storage.OpenOrCreate(StoragePath);
                    var page = manager.FetchPage(index);
                    Assert.AreEqual(resurrectIndex, page.Index);
                    Assert.AreEqual(0xff, page.Content[10]);
                }
        }