Skip to content

Commit 5a2c22f

Browse files
committed
new files
1 parent 4148f95 commit 5a2c22f

File tree

6 files changed

+966
-0
lines changed

6 files changed

+966
-0
lines changed

uBtreePage.pas

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
unit uBtreePage;
2+
3+
interface
4+
5+
uses
6+
Windows, SysUtils, uStructs;
7+
8+
const
9+
pag_left = $01; // Ýòî ñàìàÿ ëåâàÿ ñòðàíèöà â óðîâíå
10+
pag_root = $02; // Ýòî êîðíåâàÿ ñòðàíèöà
11+
pag_leaf = $04; // Ýòî ëèñòîâàÿ ñòðàíèöà
12+
13+
key_delete = $01; // Êëþ÷ ïîìå÷åí êàê óäàë¸ííûé
14+
key_right = $02; // Êëþ÷ óêàçûâàåò íà ïðàâûé óçåë (âíóòðåííèé óçåë)
15+
key_bias = $04; // Êëþ÷ ÿâëÿåòñÿ ñìåùåííûì (bias key)
16+
key_dupeq = $08; // Êëþ÷ ïîìå÷åí êàê äóáëèêàò (äëÿ óíèêàëüíûõ èíäåêñîâ)
17+
18+
type
19+
// Ôèêñèðîâàííàÿ ÷àñòü çàãîëîâêà B-Tree ñòðàíèöû
20+
TBtreePageHeader = packed record
21+
pag_header: TPag; // 0x00-0x0F - Ñòàíäàðòíûé çàãîëîâîê
22+
pag_next: SLong; // 0x10-0x13 - Óêàçàòåëü íà ñëåäóþùóþ ñòðàíèöó (ëèñò)
23+
pag_sibling: SLong;// 0x14-0x17 - Óêàçàòåëü íà ñîñåäíþþ ñòðàíèöó
24+
pag_parent: SLong; // 0x18-0x1B - Óêàçàòåëü íà ðîäèòåëüñêóþ ñòðàíèöó
25+
pag_count: UShort; // 0x1C-0x1D - Êîëè÷åñòâî êëþ÷åé íà ñòðàíèöå
26+
pag_flags: UChar; // 0x1E - Ôëàãè ñòðàíèöû
27+
pag_fill: UChar; // 0x1F - Ïðîöåíò çàïîëíåíèÿ (íå èñïîëüçóåòñÿ)
28+
// pag_keys íà÷èíàåòñÿ ñ áàéòà 0x20
29+
end;
30+
31+
// Òèï äëÿ ïðåäñòàâëåíèÿ îäíîãî êëþ÷à
32+
TBtreeKey = record
33+
Length: UShort;
34+
Flags: SChar;
35+
Data: TBytes; // Äàííûå êëþ÷à
36+
PageOrRecordNumber: SLong; // Äëÿ âíóòðåííèõ óçëîâ - íîìåð ñòðàíèöû, äëÿ ëèñòüåâ - íîìåð çàïèñè
37+
end;
38+
39+
// Òèï äëÿ ìàññèâà êëþ÷åé
40+
TBtreeKeyArray = array of TBtreeKey;
41+
42+
// Êëàññ äëÿ àíàëèçà B-Tree ñòðàíèöû
43+
TBtreePageAnalyzer = class
44+
private
45+
FPageSize: Integer;
46+
FPageNumber: ULong; // Íîìåð ñàìîé B-Tree ñòðàíèöû (ïåðåäà¸òñÿ äëÿ êîíòåêñòà)
47+
FHeader: TBtreePageHeader;
48+
FPageData: TBytes; // Äàííûå âñåé ñòðàíèöû (äëÿ èçâëå÷åíèÿ êëþ÷åé)
49+
50+
// Âíóòðåííÿÿ ôóíêöèÿ äëÿ ïîëó÷åíèÿ êëþ÷à ïî ñìåùåíèþ
51+
function GetKeyAtOffset(Offset: Integer): TBtreeKey;
52+
public
53+
// Êîíñòðóêòîð - ïðèíèìàåò áàéòû ñòðàíèöû, ðàçìåð ñòðàíèöû è íîìåð ñòðàíèöû
54+
constructor Create(const PageBuffer: TBytes; PageSize: Integer; PageNum: ULong);
55+
56+
// Ïîëó÷èòü ìàññèâ âñåõ êëþ÷åé íà ñòðàíèöå
57+
function GetKeys: TBtreeKeyArray;
58+
59+
// Ïîëó÷èòü ôëàãè ñòðàíèöû
60+
property Flags: UChar read FHeader.pag_flags;
61+
// Ïîëó÷èòü êîëè÷åñòâî êëþ÷åé
62+
property Count: UShort read FHeader.pag_count;
63+
// Ïîëó÷èòü íîìåð ñëåäóþùåé ñòðàíèöû
64+
property NextPage: SLong read FHeader.pag_next;
65+
// Ïîëó÷èòü íîìåð ñîñåäíåé ñòðàíèöû
66+
property SiblingPage: SLong read FHeader.pag_sibling;
67+
// Ïîëó÷èòü íîìåð ðîäèòåëüñêîé ñòðàíèöû
68+
property ParentPage: SLong read FHeader.pag_parent;
69+
// Ýòî ëèñòîâàÿ ñòðàíèöà?
70+
property IsLeaf: Boolean read (FHeader.pag_flags and pag_leaf) <> 0;
71+
// Ýòî êîðíåâàÿ ñòðàíèöà?
72+
property IsRoot: Boolean read (FHeader.pag_flags and pag_root) <> 0;
73+
// Ýòî ñàìàÿ ëåâàÿ ñòðàíèöà?
74+
property IsLeftmost: Boolean read (FHeader.pag_flags and pag_left) <> 0;
75+
76+
end;
77+
78+
implementation
79+
80+
constructor TBtreePageAnalyzer.Create(const PageBuffer: TBytes; PageSize: Integer; PageNum: ULong);
81+
var
82+
ExpectedMinSize: Integer;
83+
begin
84+
if (PageSize < MIN_PAGE_SIZE) or (PageSize > MAX_PAGE_SIZE) or
85+
(Length(PageBuffer) <> PageSize) then
86+
raise Exception.Create('Invalid page size or buffer size for B-Tree page.');
87+
88+
ExpectedMinSize := SizeOf(TBtreePageHeader);
89+
if Length(PageBuffer) < ExpectedMinSize then
90+
raise Exception.Create('Page buffer too small for B-Tree header.');
91+
92+
// Êîïèðóåì ôèêñèðîâàííóþ ÷àñòü çàãîëîâêà
93+
Move(PageBuffer[0], FHeader, SizeOf(TBtreePageHeader));
94+
95+
// Ïðîâåðÿåì òèï ñòðàíèöû
96+
if FHeader.pag_header.pag_type <> $07 then
97+
raise Exception.Create('Not a B-Tree Index Page.');
98+
99+
FPageSize := PageSize;
100+
FPageNumber := PageNum;
101+
FPageData := Copy(PageBuffer); // Êîïèðóåì âñå äàííûå ñòðàíèöû
102+
end;
103+
104+
function TBtreePageAnalyzer.GetKeyAtOffset(Offset: Integer): TBtreeKey;
105+
var
106+
KeyLength: UShort;
107+
KeyFlags: SChar;
108+
KeyDataOffset, KeyPageOffset: Integer;
109+
begin
110+
// Ïðîâåðÿåì ãðàíèöû
111+
if (Offset + 2 {key_length} + 1 {key_flags} > Length(FPageData)) then
112+
raise Exception.Create('Invalid offset for key in B-Tree page.');
113+
114+
// ×èòàåì key_length (2 áàéòà)
115+
KeyLength := PWord(@FPageData[Offset])^;
116+
Inc(Offset, 2);
117+
118+
// ×èòàåì key_flags (1 áàéò)
119+
KeyFlags := PShortInt(@FPageData[Offset])^;
120+
Inc(Offset, 1);
121+
122+
// Ïðîâåðÿåì, íå âûõîäèò ëè äëèíà äàííûõ çà ïðåäåëû
123+
if (Offset + KeyLength + 4 {key_page} > Length(FPageData)) then
124+
raise Exception.Create('Key length exceeds page boundary.');
125+
126+
// Êîïèðóåì key_data
127+
SetLength(Result.Data, KeyLength);
128+
if KeyLength > 0 then
129+
Move(FPageData[Offset], Result.Data[0], KeyLength);
130+
Inc(Offset, KeyLength);
131+
132+
// ×èòàåì key_page (4 áàéòà)
133+
Result.PageOrRecordNumber := PLongInt(@FPageData[Offset])^;
134+
135+
// Çàïîëíÿåì ïîëÿ ðåçóëüòàòà
136+
Result.Length := KeyLength;
137+
Result.Flags := KeyFlags;
138+
end;
139+
140+
function TBtreePageAnalyzer.GetKeys: TBtreeKeyArray;
141+
var
142+
i: Integer;
143+
CurrentOffset: Integer;
144+
Keys: TBtreeKeyArray;
145+
begin
146+
SetLength(Keys, FHeader.pag_count);
147+
148+
// Ñìåùåíèå íà÷àëà ìàññèâà êëþ÷åé
149+
CurrentOffset := SizeOf(TBtreePageHeader);
150+
151+
for i := 0 to FHeader.pag_count - 1 do
152+
begin
153+
Keys[i] := GetKeyAtOffset(CurrentOffset);
154+
155+
// Âû÷èñëÿåì ñìåùåíèå ñëåäóþùåãî êëþ÷à
156+
// key_length(2) + key_flags(1) + key_data(key_length) + key_page(4)
157+
CurrentOffset := CurrentOffset + 2 + 1 + Keys[i].Length + 4;
158+
end;
159+
160+
Result := Keys;
161+
end;
162+
163+
end.

uDatabaseStats.pas

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
unit uDatabaseStats;
2+
3+
interface
4+
5+
uses
6+
Classes, uPageAnalyzer, uDataPage, uTipPage, uBtreePage;
7+
8+
type
9+
SChar = Shortint;
10+
SShort = Smallint;
11+
UShort = Word;
12+
SLong = Longint;
13+
ULong = LongWord;
14+
UChar = type Byte;
15+
16+
TPageTypeStats = record
17+
HeaderPages: ULong;
18+
PipPages: ULong;
19+
TipPages: ULong;
20+
PointerPages: ULong;
21+
DataPages: ULong;
22+
IndexRootPages: ULong;
23+
IndexBtreePages: ULong;
24+
BlobPages: ULong;
25+
GeneratorPages: ULong;
26+
WalPages: ULong;
27+
UnknownPages: ULong;
28+
end;
29+
30+
31+
TTransactionStats = record
32+
Active: ULong;
33+
Limbo: ULong;
34+
Dead: ULong;
35+
Committed: ULong;
36+
Total: ULong;
37+
end;
38+
39+
40+
TRelationStats = record
41+
RelationID: ULong;
42+
PageCount: ULong; // Êîëè÷åñòâî Data Pages, ïðèíàäëåæàùèõ îòíîøåíèþ
43+
RecordCount: ULong; // Ïðèìåð: êîëè÷åñòâî çàïèñåé (òðåáóåò ïàðñèíãà ôðàãìåíòîâ)
44+
end;
45+
TRelationStatsArray = array of TRelationStats;
46+
47+
TDatabaseStats = class
48+
private
49+
FPageAnalyzer: TPageAnalyzer;
50+
FPageStats: TPageTypeStats;
51+
FTransactionStats: TTransactionStats;
52+
FRelationStats: TRelationStatsArray;
53+
FStatsCalculated: Boolean;
54+
55+
// Âíóòðåííÿÿ ôóíêöèÿ äëÿ ïîäñ÷åòà òèïîâ ñòðàíèö
56+
procedure CalculatePageStats;
57+
// Âíóòðåííÿÿ ôóíêöèÿ äëÿ ïîäñ÷åòà ñòàòèñòèêè ïî TIP
58+
procedure CalculateTransactionStats;
59+
// Âíóòðåííÿÿ ôóíêöèÿ äëÿ ïîäñ÷åòà ñòàòèñòèêè ïî îòíîøåíèÿì (óïðîùåííàÿ)
60+
procedure CalculateRelationStats;
61+
public
62+
// Êîíñòðóêòîð - ïðèíèìàåò TPageAnalyzer
63+
constructor Create(APageAnalyzer: TPageAnalyzer);
64+
// Äåñòðóêòîð
65+
destructor Destroy; override;
66+
67+
// Âû÷èñëèòü âñþ ñòàòèñòèêó
68+
procedure CalculateStats;
69+
70+
// Ïîëó÷èòü ñòàòèñòèêó ïî òèïàì ñòðàíèö
71+
property PageStats: TPageTypeStats read FPageStats;
72+
// Ïîëó÷èòü ñòàòèñòèêó ïî òðàíçàêöèÿì
73+
property TransactionStats: TTransactionStats read FTransactionStats;
74+
// Ïîëó÷èòü ñòàòèñòèêó ïî îòíîøåíèÿì
75+
property RelationStats: TRelationStatsArray read FRelationStats;
76+
// Ñòàòèñòèêà óæå âû÷èñëåíà?
77+
property StatsCalculated: Boolean read FStatsCalculated;
78+
end;
79+
80+
implementation
81+
82+
uses
83+
SysUtils;
84+
85+
constructor TDatabaseStats.Create(APageAnalyzer: TPageAnalyzer);
86+
begin
87+
inherited Create;
88+
FPageAnalyzer := APageAnalyzer;
89+
FStatsCalculated := False;
90+
end;
91+
92+
destructor TDatabaseStats.Destroy;
93+
begin
94+
inherited;
95+
end;
96+
97+
procedure TDatabaseStats.CalculatePageStats;
98+
var
99+
PageNum: ULong;
100+
PageInfo: TPageInfo;
101+
begin
102+
103+
FillChar(FPageStats, SizeOf(FPageStats), 0);
104+
105+
for PageNum := 0 to FPageAnalyzer.GetLastPageNumber do
106+
begin
107+
PageInfo := FPageAnalyzer.GetPageInfo(PageNum);
108+
case PageInfo.Header.pag_type of
109+
pag_header: Inc(FPageStats.HeaderPages);
110+
pag_pip: Inc(FPageStats.PipPages);
111+
pag_tip: Inc(FPageStats.TipPages);
112+
pag_pointer: Inc(FPageStats.PointerPages);
113+
pag_data: Inc(FPageStats.DataPages);
114+
pag_index_root: Inc(FPageStats.IndexRootPages);
115+
pag_index_bt: Inc(FPageStats.IndexBtreePages);
116+
pag_blob: Inc(FPageStats.BlobPages);
117+
pag_generator: Inc(FPageStats.GeneratorPages);
118+
pag_wal: Inc(FPageStats.WalPages);
119+
else
120+
Inc(FPageStats.UnknownPages);
121+
end;
122+
end;
123+
end;
124+
125+
procedure TDatabaseStats.CalculateTransactionStats;
126+
var
127+
PageNum: ULong;
128+
PageInfo: TPageInfo;
129+
TipAnalyzer: TTIPAnalyzer;
130+
TxInfoArray: TTransactionInfoArray;
131+
i: Integer;
132+
begin
133+
// Èíèöèàëèçèðóåì ñ÷åò÷èêè
134+
FillChar(FTransactionStats, SizeOf(FTransactionStats), 0);
135+
136+
for PageNum := 0 to FPageAnalyzer.GetLastPageNumber do
137+
begin
138+
PageInfo := FPageAnalyzer.GetPageInfo(PageNum);
139+
if PageInfo.Header.pag_type = pag_tip then
140+
begin
141+
TipAnalyzer := TTIPAnalyzer.Create(PageInfo.Buffer, PageInfo.Size, PageInfo.Number);
142+
try
143+
TxInfoArray := TipAnalyzer.GetTransactionInfo(); // Ïîëó÷èòü âñå òðàíçàêöèè íà ñòðàíèöå
144+
for i := 0 to High(TxInfoArray) do
145+
begin
146+
case TxInfoArray[i].State of
147+
tsActive: Inc(FTransactionStats.Active);
148+
tsLimbo: Inc(FTransactionStats.Limbo);
149+
tsDead: Inc(FTransactionStats.Dead);
150+
tsCommitted: Inc(FTransactionStats.Committed);
151+
end;
152+
Inc(FTransactionStats.Total);
153+
end;
154+
finally
155+
TipAnalyzer.Free;
156+
end;
157+
end;
158+
end;
159+
end;
160+
161+
procedure TDatabaseStats.CalculateRelationStats;
162+
var
163+
PageNum: ULong;
164+
PageInfo: TPageInfo;
165+
DataPageHeader: TData_Page_Fixed_Part;
166+
Fragments: TRecordFragmentsArray;
167+
FoundRelation: Boolean;
168+
i, j: Integer;
169+
begin
170+
SetLength(FRelationStats, 0);
171+
172+
for PageNum := 0 to FPageAnalyzer.GetLastPageNumber do
173+
begin
174+
PageInfo := FPageAnalyzer.GetPageInfo(PageNum);
175+
if PageInfo.Header.pag_type = pag_data then
176+
begin
177+
if Length(PageInfo.Buffer) >= SizeOf(TData_Page_Fixed_Part) then
178+
begin
179+
DataPageHeader := TData_Page_Fixed_Part(PageInfo.Buffer[0]);
180+
var RelationID := DataPageHeader.dpg_relation;
181+
182+
FoundRelation := False;
183+
for j := 0 to High(FRelationStats) do
184+
begin
185+
if FRelationStats[j].RelationID = RelationID then
186+
begin
187+
Inc(FRelationStats[j].PageCount);
188+
FoundRelation := True;
189+
Break;
190+
end;
191+
end;
192+
193+
194+
if not FoundRelation then
195+
begin
196+
SetLength(FRelationStats, Length(FRelationStats) + 1);
197+
FRelationStats[High(FRelationStats)].RelationID := RelationID;
198+
FRelationStats[High(FRelationStats)].PageCount := 1;
199+
FRelationStats[High(FRelationStats)].RecordCount := 0;
200+
end;
201+
202+
203+
Fragments := ExtractDataFragments(PageInfo.Buffer, PageInfo.Size);
204+
205+
for j := 0 to High(FRelationStats) do
206+
begin
207+
if FRelationStats[j].RelationID = RelationID then
208+
begin
209+
Inc(FRelationStats[j].RecordCount, Length(Fragments));
210+
Break;
211+
end;
212+
end;
213+
end;
214+
end;
215+
end;
216+
end;
217+
218+
procedure TDatabaseStats.CalculateStats;
219+
begin
220+
CalculatePageStats;
221+
CalculateTransactionStats;
222+
CalculateRelationStats;
223+
FStatsCalculated := True;
224+
end;
225+
226+
end.

0 commit comments

Comments
 (0)