private LoadedPage MapPages(TransactionState state, long startPage, long size)
        {
            _globalMemory.EnterReadLock();
            try
            {
                var addresses = _globalMapping.GetOrAdd(startPage,
                                                        _ => new ConcurrentSet <MappedAddresses>());
                foreach (var addr in addresses)
                {
                    if (addr.Size < size)
                    {
                        continue;
                    }

                    Interlocked.Increment(ref addr.Usages);
                    return(AddMappingToTransaction(state, startPage, size, addr));
                }

                var offset = startPage * Constants.Storage.PageSize;

                if (offset + size > _totalAllocationSize)
                {
                    ThrowInvalidMappingRequested(startPage, size);
                }
                var mmflags = _copyOnWriteMode ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED;

                var startingBaseAddressPtr = Syscall.mmap64(IntPtr.Zero, (UIntPtr)size,
                                                            MmapProts.PROT_READ | MmapProts.PROT_WRITE,
                                                            mmflags, _fd, offset);

                if (startingBaseAddressPtr.ToInt64() == -1)
                //system didn't succeed in mapping the address where we wanted
                {
                    var err = Marshal.GetLastWin32Error();

                    Syscall.ThrowLastError(err,
                                           $"Unable to map {size / Constants.Size.Kilobyte:#,#0} kb starting at {startPage} on {FileName}");
                }

                NativeMemory.RegisterFileMapping(FileName.FullPath, startingBaseAddressPtr, size, GetAllocatedInBytes);

                Interlocked.Add(ref _totalMapped, size);
                var mappedAddresses = new MappedAddresses
                {
                    Address   = startingBaseAddressPtr,
                    File      = FileName.FullPath,
                    Size      = size,
                    StartPage = startPage,
                    Usages    = 1
                };
                addresses.Add(mappedAddresses);
                return(AddMappingToTransaction(state, startPage, size, mappedAddresses));
            }
            finally
            {
                _globalMemory.ExitReadLock();
            }
        }
        private LoadedPage AddMappingToTransaction(TransactionState state, long startPage, long size, MappedAddresses mappedAddresses)
        {
            state.TotalLoadedSize += size;
            state.AddressesToUnload.Add(mappedAddresses);
            var loadedPage = new LoadedPage
            {
                Pointer       = (byte *)mappedAddresses.Address,
                NumberOfPages = (int)(size / Constants.Storage.PageSize),
                StartPage     = startPage
            };

            state.LoadedPages[startPage] = loadedPage;
            return(loadedPage);
        }