public byte[] GetPageBytes(PagePointer loc, bool putResultToCache = true)
        {
            if (!_backupMode)
            {
                return(_bufferManager.GetPageBytes(loc.FileID, loc.PageID, putResultToCache));
            }

            //var pagesInFile = (int)(bufferManager.GetFileLen(loc.FileID) / 8192);

            //var pages = Enumerable.Range(0, pagesInFile).Select(x => new PagePointer(loc.FileID, x)).ToArray();

            //var result = ( from pagePointer in pages
            //               let pageHeaderBytes = bufferManager.GetHeaderBytes(pagePointer.FileID, pagePointer.PageID)
            //               let pageHeader = new PageHeader(pageHeaderBytes)
            //               select new Tuple<PagePointer, PagePointer>(pagePointer, pageHeader.Pointer)
            //              ).ToList();

            //File.WriteAllText("test.loc.txt", string.Join(Environment.NewLine, result.Select(x => x.Item1 + " -> " + x.Item2)));


            if (_backupPagesMap.TryGetValue(loc.FileID, out var loc1) && loc1.TryGetValue(loc.PageID / 8, out var loc2))
            {
                return(_bufferManager.GetPageBytes(loc2.FileID, loc2.PageID + loc.PageID % 8, putResultToCache));
            }

            var pointer = BinarySearch(x => new PageHeader(_bufferManager.GetHeaderBytes(loc.FileID, x * 8)).Pointer,
                                       0, (long)_bufferManager.GetFileLen(loc.FileID) / (8192 * 8), loc);

            return(_bufferManager.GetPageBytes(pointer.FileID, pointer.PageID + loc.PageID % 8, putResultToCache));
        }
Exemple #2
0
        internal GamPage GetGamPage(PagePointer loc)
        {
            Debug.WriteLine("Loading GAM Page " + loc);

            if (loc.PageID % 511230 != 2)
            {
                throw new ArgumentException("Invalid GAM index: " + loc.PageID);
            }

            return(new GamPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #3
0
        internal CompressedRecordPage GetCompressedRecordPage(PagePointer loc, CompressionContext compression)
        {
            if (compression.CompressionLevel == CompressionLevel.None)
            {
                throw new ArgumentException("Can't load compressed page with a compression level of none.");
            }

            Debug.WriteLine("Loading compressed record page " + loc);

            return(new CompressedRecordPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), compression, this));
        }
Exemple #4
0
        /// <summary>
        /// Starts at the data page (loc) and follows the NextPage pointer chain till the end.
        /// </summary>
        internal IEnumerable<Row> ScanLinkedNonclusteredIndexPages(PagePointer loc, Row schema, CompressionContext compression)
        {
            while (loc != PagePointer.Zero)
            {
                var page = Database.GetNonclusteredIndexPage(loc);

                foreach (var dr in page.GetEntities(schema, compression))
                    yield return dr;

                loc = page.Header.NextPage;
            }
        }
Exemple #5
0
        internal PfsPage GetPfsPage(PagePointer loc)
        {
            Debug.WriteLine("Loading PFS Page " + loc);

            // We know PFS pages are present every 8088th page, except for the very first one
            if (loc.PageID != 1 && loc.PageID % 8088 != 0)
            {
                throw new ArgumentException("Invalid PFS index: " + loc.PageID);
            }

            return(new PfsPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #6
0
        /// <summary>
        /// Starts at the data page (loc) and follows the NextPage pointer chain till the end.
        /// </summary>
        internal IEnumerable <Row> ScanLinkedDataPages(PagePointer loc, Row schema, CompressionContext compression)
        {
            while (loc != PagePointer.Zero)
            {
                var recordParser = RecordEntityParser.CreateEntityParserForPage(loc, compression, Database);

                foreach (var dr in recordParser.GetEntities(schema))
                {
                    yield return(dr);
                }

                loc = recordParser.NextPage;
            }
        }
Exemple #7
0
        /// <summary>
        /// Starts at the data page (loc) and follows the NextPage pointer chain till the end.
        /// </summary>
        internal IEnumerable <Row> ScanLinkedNonclusteredIndexPages(PagePointer loc, Row schema, CompressionContext compression)
        {
            while (loc != PagePointer.Zero)
            {
                var page = Database.GetNonclusteredIndexPage(loc);

                foreach (var dr in page.GetEntities(schema, compression))
                {
                    yield return(dr);
                }

                loc = page.Header.NextPage;
            }
        }
Exemple #8
0
        internal FileHeaderPage GetFileHeaderPage(PagePointer loc)
        {
            Debug.WriteLine("Loading File Header Page");

            return(new FileHeaderPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #9
0
        private void parseSyssingleobjrefs()
        {
            // Using a fixed object ID, we can look up the partition for sysscalartypes and scan the hobt AU from there
            long rowsetID = sysrowsets
                .Where(x => x.idmajor == (int)SystemObject.syssingleobjrefs && x.idminor == 1)
                .Single()
                .rowsetid;

            var pageLoc = new PagePointer(
                sysallocunits
                    .Where(x => x.auid == rowsetID && x.type == 1)
                    .Single()
                    .pgfirst
            );

            syssingleobjrefs = scanner.ScanLinkedDataPages<syssingleobjref>(pageLoc, CompressionContext.NoCompression).ToList();
        }
        private PagePointer BinarySearch(Func <long, PagePointer> getPagePointerFunc, long l, long r, PagePointer x)
        {
            var range           = new Range();
            var firstExtentPage = new PagePointer(x.FileID, x.PageID / 8 * 8);

            if (!_backupPagesMap.ContainsKey(x.FileID))
            {
                _backupPagesMap[x.FileID] = new Dictionary <long, PagePointer>();
            }

            l = _backupPagesMap[x.FileID].Select(y => new { Diff = firstExtentPage.PageID / 8 - y.Key, Key = (long?)y.Value.PageID / 8 })
                .Where(y => y.Diff >= 0)
                .OrderBy(y => y.Diff)
                .Select(y => y.Key)
                .FirstOrDefault() ?? l;

            r = _backupPagesMap[x.FileID].Select(y => new { Diff = y.Key - firstExtentPage.PageID / 8, Key = (long?)y.Value.PageID / 8 })
                .Where(y => y.Diff >= 0)
                .OrderBy(y => y.Diff)
                .Select(y => y.Key)
                .FirstOrDefault() ?? r;

            if (l + 1 == firstExtentPage.PageID / 8)
            {
                var pagePointer = getPagePointerFunc(l + 1);

                _backupPagesMap[pagePointer.FileID][pagePointer.PageID / 8] = new PagePointer(pagePointer.FileID, (l + 1) * 8);

                if (pagePointer == firstExtentPage)
                {
                    return(new PagePointer(pagePointer.FileID, (l + 1) * 8));
                }
            }

            while (l <= r)
            {
                var m = l + (r - l) / 2;

                var pagePointer = getPagePointerFunc(m);

                if (pagePointer != PagePointer.Zero)
                {
                    _backupPagesMap[pagePointer.FileID][pagePointer.PageID / 8] = new PagePointer(pagePointer.FileID, m * 8);
                }

                // Check if x is present at mid
                if (pagePointer == firstExtentPage)
                {
                    return(new PagePointer(pagePointer.FileID, m * 8));
                }

                // If x greater, ignore left half
                if (pagePointer.PageID < firstExtentPage.PageID)// && pagePointer != PagePointer.Zero)
                {
                    l = m + 1;
                }

                // If x is smaller, ignore right half
                else
                {
                    r = m - 1;
                }
            }

            // We reach here when element is not present in array
            return(PagePointer.Zero);
        }
Exemple #11
0
        internal IamPage GetIamPage(PagePointer loc)
        {
            Debug.WriteLine("Loading IAM Page " + loc);

            return(new IamPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #12
0
        internal PfsPage GetPfsPage(PagePointer loc)
        {
            Debug.WriteLine("Loading PFS Page " + loc);

            // We know PFS pages are present every 8088th page, except for the very first one
            if (loc.PageID != 1 && loc.PageID % 8088 != 0)
                throw new ArgumentException("Invalid PFS index: " + loc.PageID);

            return new PfsPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #13
0
        internal Page GetPage(PagePointer loc)
        {
            Debug.WriteLine("Loading Generic Page " + loc);

            return new Page(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #14
0
        internal NonclusteredIndexPage GetNonclusteredIndexPage(PagePointer loc)
        {
            Debug.WriteLine("Loading Nonclustered Index Page " + loc);

            return new NonclusteredIndexPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #15
0
        internal FileHeaderPage GetFileHeaderPage(PagePointer loc)
        {
            Debug.WriteLine("Loading File Header Page");

            return new FileHeaderPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #16
0
        internal CompressedRecordPage GetCompressedRecordPage(PagePointer loc, CompressionContext compression)
        {
            if (compression.CompressionLevel == CompressionLevel.None)
                throw new ArgumentException("Can't load compressed page with a compression level of none.");

            Debug.WriteLine("Loading compressed record page " + loc);

            return new CompressedRecordPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), compression, this);
        }
Exemple #17
0
        internal ClusteredIndexPage GetClusteredIndexPage(PagePointer loc)
        {
            Debug.WriteLine("Loading Clustered Index Page " + loc);

            return(new ClusteredIndexPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #18
0
        internal TextMixPage GetTextMixPage(PagePointer loc)
        {
            Debug.WriteLine("Loading TextMix Page " + loc);

            return(new TextMixPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this));
        }
Exemple #19
0
 public ExtentPointer(PagePointer start)
 {
     StartPage = start;
     EndPage = new PagePointer(start.FileID, start.PageID + 7);
 }
Exemple #20
0
        internal PrimaryRecordPage GetPrimaryRecordPage(PagePointer loc, CompressionContext compression)
        {
            Debug.WriteLine("Loading Primary Record Page " + loc);

            return new PrimaryRecordPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), compression, this);
        }
 public ExtentPointer(PagePointer start)
 {
     StartPage = start;
     EndPage   = new PagePointer(start.FileID, start.PageID + 7);
 }
Exemple #22
0
        internal PrimaryRecordPage GetPrimaryRecordPage(PagePointer loc, CompressionContext compression)
        {
            Debug.WriteLine("Loading Primary Record Page " + loc);

            return(new PrimaryRecordPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), compression, this));
        }
Exemple #23
0
        internal SgamPage GetSgamPage(PagePointer loc)
        {
            Debug.WriteLine("Loading SGAM Page " + loc);

            if (loc.PageID % 511230 != 3)
                throw new ArgumentException("Invalid SGAM index: " + loc.PageID);

            return new SgamPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #24
0
        /// <summary>
        /// Will scan any table - heap or clustered - and return an IEnumerable of typed rows with data & schema
        /// </summary>
        //internal IEnumerable<TDataRow> ScanTable<TDataRow>(string tableName) where TDataRow : Row, new()
        //{
        //    //var schema = new TDataRow();

        //    //return scanTable(tableName, schema).Cast<TDataRow>();
        //}

        /// <summary>
        /// Scans a linked list of pages returning an IEnumerable of typed rows with data & schema
        /// </summary>
        internal IEnumerable <TDataRow> ScanLinkedDataPages <TDataRow>(PagePointer loc, CompressionContext compression) where TDataRow : Row, new()
        {
            return(ScanLinkedDataPages(loc, new TDataRow(), compression).Cast <TDataRow>());
        }
Exemple #25
0
        internal TextMixPage GetTextMixPage(PagePointer loc)
        {
            Debug.WriteLine("Loading TextMix Page " + loc);

            return new TextMixPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this);
        }
Exemple #26
0
        /// <summary>
        /// Scans a heap beginning from the provided IAM page and onwards.
        /// </summary>
        private IEnumerable <Row> scanHeap(PagePointer loc, Row schema, CompressionContext compression)
        {
            // Traverse the linked list of IAM pages untill the tail pointer is zero
            while (loc != PagePointer.Zero)
            {
                // Before scanning, check that the IAM page itself is allocated
                var pfsPage = Database.GetPfsPage(PfsPage.GetPfsPointerForPage(loc));

                // If IAM page isn't allocated, there's nothing to return
                if (!pfsPage.GetPageDescription(loc.PageID).IsAllocated)
                {
                    yield break;
                }

                var iamPage = Database.GetIamPage(loc);

                // Create an array with all of the header slot pointers
                var iamPageSlots = new[]
                {
                    iamPage.Slot0,
                    iamPage.Slot1,
                    iamPage.Slot2,
                    iamPage.Slot3,
                    iamPage.Slot4,
                    iamPage.Slot5,
                    iamPage.Slot6,
                    iamPage.Slot7
                };

                // Loop each header slot and yield the results, provided the header slot is allocated
                foreach (var slot in iamPageSlots.Where(x => x != PagePointer.Zero))
                {
                    var recordParser = RecordEntityParser.CreateEntityParserForPage(slot, compression, Database);

                    foreach (var dr in recordParser.GetEntities(schema))
                    {
                        yield return(dr);
                    }
                }

                // Then loop through allocated extents and yield results
                foreach (var extent in iamPage.GetAllocatedExtents())
                {
                    // Get PFS page that tracks this extent
                    var pfs = Database.GetPfsPage(PfsPage.GetPfsPointerForPage(extent.StartPage));

                    foreach (var pageLoc in extent.GetPagePointers())
                    {
                        // Check if page is allocated according to PFS page
                        var pfsDescription = pfs.GetPageDescription(pageLoc.PageID);

                        if (!pfsDescription.IsAllocated)
                        {
                            continue;
                        }

                        var recordParser = RecordEntityParser.CreateEntityParserForPage(pageLoc, compression, Database);

                        foreach (var dr in recordParser.GetEntities(schema))
                        {
                            yield return(dr);
                        }
                    }
                }

                // Update current IAM chain location to the tail pointer
                loc = iamPage.Header.NextPage;
            }
        }
Exemple #27
0
        private void parseSysrowsets()
        {
            // Using a fixed allocation unit ID, we can look up the hobt AU and scan it
            var pageLoc = new PagePointer(
                sysallocunits
                    .Where(x => x.auid == FixedSystemObjectAllocationUnits.sysrowsets)
                    .Single()
                    .pgfirst
            );

            sysrowsets = scanner.ScanLinkedDataPages<sysrowset>(pageLoc, CompressionContext.NoCompression).ToList();
        }