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)); }
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)); }
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)); }
/// <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; } }
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)); }
/// <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; } }
/// <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; } }
internal FileHeaderPage GetFileHeaderPage(PagePointer loc) { Debug.WriteLine("Loading File Header Page"); return(new FileHeaderPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this)); }
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); }
internal IamPage GetIamPage(PagePointer loc) { Debug.WriteLine("Loading IAM Page " + loc); return(new IamPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this)); }
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); }
internal Page GetPage(PagePointer loc) { Debug.WriteLine("Loading Generic Page " + loc); return new Page(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this); }
internal NonclusteredIndexPage GetNonclusteredIndexPage(PagePointer loc) { Debug.WriteLine("Loading Nonclustered Index Page " + loc); return new NonclusteredIndexPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this); }
internal FileHeaderPage GetFileHeaderPage(PagePointer loc) { Debug.WriteLine("Loading File Header Page"); return new FileHeaderPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this); }
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); }
internal ClusteredIndexPage GetClusteredIndexPage(PagePointer loc) { Debug.WriteLine("Loading Clustered Index Page " + loc); return(new ClusteredIndexPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this)); }
internal TextMixPage GetTextMixPage(PagePointer loc) { Debug.WriteLine("Loading TextMix Page " + loc); return(new TextMixPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this)); }
public ExtentPointer(PagePointer start) { StartPage = start; EndPage = new PagePointer(start.FileID, start.PageID + 7); }
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); }
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)); }
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); }
/// <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>()); }
internal TextMixPage GetTextMixPage(PagePointer loc) { Debug.WriteLine("Loading TextMix Page " + loc); return new TextMixPage(bufferManager.GetPageBytes(loc.FileID, loc.PageID), this); }
/// <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; } }
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(); }