예제 #1
0
        public void should_allow_multiple_transactions_to_append_records()
        {
            const ushort objectType  = 128;
            const int    threadCount = 5;

            var threads         = new List <Thread>();
            var exceptions      = new List <Exception>();
            var firstPageNumber = _pageStore.GetFirstIndexPage(objectType);

            for (var i = 1; i <= threadCount; i++)
            {
                var transactionNumber = i;
                var thread            = new Thread(() =>
                {
                    try
                    {
                        var writeTransaction = _database.BeginTransaction(null);
                        _pageStore.BeginTransaction(writeTransaction);

                        var buffer   = Encoding.UTF8.GetBytes("Transaction " + transactionNumber);
                        var location = _accessor.Append(firstPageNumber, writeTransaction, (uint)buffer.LongLength);
                        _accessor.Write(writeTransaction, location, buffer);

                        Thread.Sleep(50);

                        _database.CommitTransaction(writeTransaction);
                        _pageStore.CommitTransaction(writeTransaction);
                        _pageStore.FinalizeTransaction(writeTransaction);
                    }
                    catch (Exception ex)
                    {
                        lock (exceptions)
                            exceptions.Add(ex);
                    }
                })
                {
                    Name         = "Transaction " + i,
                    IsBackground = true
                };
                threads.Add(thread);
            }

            foreach (var thread in threads)
            {
                thread.Start();
            }
            foreach (var thread in threads)
            {
                thread.Join();
            }

            Assert.AreEqual(0, exceptions.Count);

            var transaction = _database.BeginTransaction(null);

            _pageStore.BeginTransaction(transaction);

            var results = new HashSet <string>();

            Action <PageLocation> check = (location) =>
            {
                using (var page = _pageStore.Get(transaction, location.PageNumber, CacheHints.None))
                {
                    var actual = Encoding.UTF8.GetString(page.Data, (int)location.Offset, (int)location.Length);
                    Assert.IsTrue(results.Add(actual));
                }
            };

            var record = _accessor.LocateFirst(firstPageNumber, transaction, out object indexLocation);

            Assert.IsNotNull(record);

            for (var i = 1; i <= threadCount; i++)
            {
                check(record);
                record = _accessor.LocateNext(firstPageNumber, transaction, indexLocation);
            }

            for (var i = 1; i <= threadCount; i++)
            {
                Assert.IsTrue(results.Contains("Transaction " + i));
            }

            Assert.IsNull(record);
        }
        public void should_read_and_write_records()
        {
            const ushort objectType = 128;

            var strings = new[]
            {
                "The short brown lazy dog couldn't jump over anything",
                "One, two, buckle my shoe",
                "YARD (Yet Another Relational Database)",
                "This is a test, one, two, three, testing",
                "Blah blah blah",
                "This should be on a second index page",
                "OK, I think that's enough now"
            };

            var transaction = _database.BeginTransaction(null);

            _pageStore.BeginTransaction(transaction);

            var firstPageNumber = _pageStore.GetFirstIndexPage(objectType);

            _accessor.Clear(firstPageNumber, transaction);

            foreach (var s in strings)
            {
                var buffer         = Encoding.UTF8.GetBytes(s);
                var recordLocation = _accessor.Append(firstPageNumber, transaction, (uint)buffer.LongLength);
                _accessor.Write(transaction, recordLocation, buffer);
            }

            _database.CommitTransaction(transaction);
            _pageStore.CommitTransaction(transaction);
            _pageStore.FinalizeTransaction(transaction);

            transaction = _database.BeginTransaction(null);
            _pageStore.BeginTransaction(transaction);

            Action <PageLocation, string> check = (location, expected) =>
            {
                Assert.IsNotNull(location);

                var data   = location.ReadAll(transaction, CacheHints.None);
                var actual = Encoding.UTF8.GetString(data);

                Assert.AreEqual(expected, actual);
            };

            var record = _accessor.LocateFirst(firstPageNumber, transaction, out object indexLocation);

            Assert.IsNotNull(record);

            foreach (var s in strings)
            {
                check(record, s);
                record = _accessor.LocateNext(firstPageNumber, transaction, indexLocation);
            }

            Assert.IsNull(record);

            _database.RollbackTransaction(transaction);
            _pageStore.RollbackTransaction(transaction);
        }
예제 #3
0
        public void should_allow_relocking_a_page()
        {
            var pageNumber = _pageStore.GetFirstIndexPage(128);

            // Update a page without a lock

            var updateTransaction = _database.BeginTransaction(null);

            _pageStore.BeginTransaction(updateTransaction);

            _pageStore.Update(
                updateTransaction, new[]
            {
                new PageUpdate
                {
                    PageNumber = pageNumber,
                    Offset     = 3,
                    Data       = new byte[] { 98, 99, 100 }
                }
            });

            // Lock and update the page multiple times

            for (byte i = 10; i < 15; i++)
            {
                _pageStore.Lock(updateTransaction, pageNumber);

                _pageStore.Update(
                    updateTransaction, new[]
                {
                    new PageUpdate
                    {
                        PageNumber = pageNumber,
                        Offset     = i,
                        Data       = new byte[] { i }
                    }
                });
            }

            // Commit all the changes to disk

            _database.CommitTransaction(updateTransaction);
            _pageStore.CommitTransaction(updateTransaction);
            _pageStore.FinalizeTransaction(updateTransaction);

            // Check that the changes were written properly

            var readTransaction = _database.BeginTransaction(null);

            _pageStore.BeginTransaction(readTransaction);

            using (var page = _pageStore.Get(readTransaction, pageNumber, CacheHints.None))
            {
                Assert.AreEqual(98, page.Data[3]);
                Assert.AreEqual(99, page.Data[4]);
                Assert.AreEqual(100, page.Data[5]);
                Assert.AreEqual(10, page.Data[10]);
                Assert.AreEqual(11, page.Data[11]);
                Assert.AreEqual(12, page.Data[12]);
                Assert.AreEqual(13, page.Data[13]);
                Assert.AreEqual(14, page.Data[14]);
            }

            _database.RollbackTransaction(readTransaction);
            _pageStore.RollbackTransaction(readTransaction);
        }