Ejemplo n.º 1
0
        public async Task <IPage> AllocatePage(PageType pageType, ColumnInfo[] columnTypes, ulong prevPageId, ulong nextPageId, ulong pageId, ITransaction tran)
        {
            logger.LogDebug($"Allocating new page {pageId}");
            IPage page;

            using Releaser releaser = await tran.AcquireLockWithCallerOwnership(pageId, LockTypeEnum.Exclusive).ConfigureAwait(false);

            (Memory <byte> memory, ulong token) = this.bufferPool.GetMemory();

            page = pageType switch
            {
                PageType.StringPage => new StringOnlyPage(pageSize, pageId, prevPageId, nextPageId, tran),
                PageType.MixedPage => new MixedPage(pageSize, pageId, columnTypes, prevPageId, nextPageId, memory, token, tran),
                _ => throw new ArgumentException("Unknown page type")
            };

            Interlocked.Increment(ref this.pageCount);

            if (prevPageId != PageManagerConstants.NullPageId)
            {
                tran.VerifyLock(prevPageId, LockTypeEnum.Exclusive);
                IPage prevPage = await GetPage(prevPageId, tran, pageType, columnTypes).ConfigureAwait(false);

                if (prevPage.NextPageId() != page.NextPageId())
                {
                    throw new ArgumentException("Breaking the link");
                }

                // TODO: Set next page id needs to be logged as well...
                prevPage.SetNextPageId(page.PageId());
            }

            if (nextPageId != PageManagerConstants.NullPageId)
            {
                IPage nextPage = await GetPage(nextPageId, tran, pageType, columnTypes).ConfigureAwait(false);

                if (nextPage.PrevPageId() != page.PrevPageId())
                {
                    throw new ArgumentException("breaking the link");
                }

                nextPage.SetPrevPageId(page.PageId());
            }

            await RecordUsageAndEvict(page.PageId(), tran).ConfigureAwait(false);

            bufferPool.AddPage(page);

            AddToAllocationMap(page);

            return(page);
        }