-
Notifications
You must be signed in to change notification settings - Fork 0
/
dot.go
99 lines (89 loc) · 3.57 KB
/
dot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package rbf
import (
"fmt"
"io"
)
func dotCell(b []byte, parent string, writer io.Writer) {
pgno := readPageNo(b)
if pgno == Magic32() {
fmt.Fprintf(writer, "==META\n")
return
}
flags := readFlags(b)
cellN := readCellN(b)
switch {
case flags&PageTypeLeaf != 0:
fmt.Fprintf(writer, "cell%d [ shape=none label=<<table border=\"0\" cellspacing=\"0\">\n", pgno)
fmt.Fprintf(writer, "<tr><td border=\"1\">CELL (%d) </td></tr>\n", pgno)
links := make([]string, 0)
for i := 0; i < cellN; i++ {
cell := readLeafCell(b, i)
switch cell.Type {
case ContainerTypeArray:
//fmt.Fprintf(os.Stderr, "[%d]: key=%d type=array n=%d elems=%v\n", i, cell.Key, cell.N, toArray16(cell.Data))
fmt.Fprintf(writer, "<tr><td border=\"1\" bgcolor=\"green\"><font color=\"white\">[%d]: key=%d type=array n=%d</font></td></tr>\n", i, cell.Key, cell.BitN)
case ContainerTypeRLE:
fmt.Fprintf(writer, "<tr><td border=\"1\" bgcolor=\"blue\"><font color=\"white\">[%d]: key=%d type=rle n=%d</font></td></tr>\n", i, cell.Key, cell.BitN)
case ContainerTypeBitmapPtr:
bpn := toPgno(cell.Data)
fmt.Fprintf(writer, "<tr><td border=\"1\" bgcolor=\"red\" port=\"%d\"><font color=\"white\">[%d]: key=%d type=bitmap n=%d </font></td></tr>\n", bpn, i, cell.Key, cell.BitN)
links = append(links, fmt.Sprintf("bitmap%d[label=\"bitmap (%d)\"]\n cell%d:%d -> bitmap%d\n", bpn, bpn, pgno, i, bpn))
default:
fmt.Fprintf(writer, "<tr><td border=\"1\" bgcolor=\"yellow\">[%d]: key=%d type=unknown<%d> n=%d</td></tr>\n", i, cell.Key, cell.Type, cell.BitN)
}
}
fmt.Fprintf(writer, "</table>>]\n")
fmt.Fprintf(writer, "%s -> cell%d\n", parent, pgno)
for _, link := range links {
fmt.Fprintf(writer, "%s", link)
}
default:
//should not happen
fmt.Fprintf(writer, "==!PAGE %d flags=%d\n", pgno, flags)
}
}
// Dumpdot recursively writes the tree representation starting from a given page to STDERR.
func Dumpdot(tx *Tx, pgno uint32, parent string, writer io.Writer) {
page, _, err := tx.readPage(pgno)
if err != nil {
panic(err)
}
if IsMetaPage(page) {
//fmt.Fprintf(writer, "META(%d)\n", pgno)
//fmt.Fprintf(writer, "└── <FREELIST>\n")
//treedump(tx, readMetaFreelistPageNo(page), indent+" ")
visitor := func(pgno uint32, records []*RootRecord) {
rr := fmt.Sprintf("rr%d", pgno)
fmt.Fprintf(writer, "%s[label=\"ROOT RECORD(%d): n=%d\"]\n", rr, pgno, len(records))
for _, record := range records {
root := fmt.Sprintf("root%d", record.Pgno)
fmt.Fprintf(writer, "%s[label=\"ROOT(%d)| %s\"]\n%s->%s\n", root, record.Pgno, record.Name, rr, root)
p := fmt.Sprintf("root%d", record.Pgno)
Dumpdot(tx, record.Pgno, p, writer)
}
}
Walk(tx, readMetaRootRecordPageNo(page), visitor)
return
}
// Handle
switch typ := readFlags(page); typ {
case PageTypeBranch:
p := fmt.Sprintf("branch%d", pgno)
fmt.Fprintf(writer, "%s[label=\"BRANCH(%d)| n=%d\"]\n %s->%s\n", p, pgno, readCellN(page), parent, p)
for i, n := 0, readCellN(page); i < n; i++ {
cell := readBranchCell(page, i)
if cell.Flags&uint32(ContainerTypeBitmap) == 0 { // leaf/branch child page
Dumpdot(tx, cell.ChildPgno, p, writer)
} else {
b := fmt.Sprintf("bm%d", cell.ChildPgno)
fmt.Fprintf(writer, "%s[label=\"BITMAP(%d) key=%d \"]\n %s -> %s\n", b, cell.ChildPgno, cell.LeftKey, p, b)
}
}
case PageTypeLeaf:
p := fmt.Sprintf("leaf%d", pgno)
fmt.Fprintf(writer, "%s[label=\"LEAF(%d)| n=%d\"]\n%s->%s\n", p, pgno, readCellN(page), parent, p)
dotCell(page, p, writer)
}
}