Пример #1
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));
        }
Пример #2
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;
            }
        }
Пример #3
0
        private void scanPartition(long partitionID, int partitionNumber, Row schema)
        {
            // Lookup partition
            var partition = Database.Dmvs.Partitions
                            .Where(p => p.PartitionID == partitionID && p.PartitionNumber == partitionNumber)
                            .SingleOrDefault();

            if (partition == null)
            {
                throw new ArgumentException("Partition (" + partitionID + "." + partitionNumber + " does not exist.");
            }

            // Get allocation unit for in-row data
            var au = Database.Dmvs.SystemInternalsAllocationUnits
                     .Where(x => x.ContainerID == partition.PartitionID && x.Type == 1)
                     .SingleOrDefault();

            if (au == null)
            {
                throw new ArgumentException("Partition (" + partition.PartitionID + "." + partition.PartitionNumber + " has no HOBT allocation unit.");
            }

            // Before we can scan either heaps or indices, we need to know the compression level as that's set at the partition level, and not at the record/page level.
            // We also need to know whether the partition is using vardecimals.
            var compression = new CompressionContext((CompressionLevel)partition.DataCompression, MetaData.PartitionHasVardecimalColumns(partition.PartitionID));

            // Heap tables won't have root pages, thus we can check whether a root page is defined for the HOBT allocation unit
            if (au.RootPage != PagePointer.Zero)
            {
                var Index = 0;
                foreach (var row in ScanLinkedDataPages(au.FirstPage, schema, compression))
                {
                    addRow(row, Index);
                    Index++;
                }
            }
            else
            {
                var index = 0;
                foreach (var row in scanHeap(au.FirstIamPage, schema, compression))
                {
                    addRow(row, index);
                    index++;
                }
            }
        }
Пример #4
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;
            }
        }
Пример #5
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>());
        }
Пример #6
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));
        }
Пример #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;
            }
        }