├── .gitignore
├── templates
├── nav.ego
├── index.ego
├── error.ego
├── head.ego
├── templates.go
├── page.ego
├── bolt.go
└── ego.go
├── Makefile
├── README.md
├── cmd
└── boltd
│ └── main.go
├── LICENSE
└── handler.go
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 |
--------------------------------------------------------------------------------
/templates/nav.ego:
--------------------------------------------------------------------------------
1 | <%! func nav(w io.Writer, tx *bolt.Tx) error %>
2 |
3 | <%% import "path/filepath" %%>
4 | <%% import "github.com/boltdb/bolt" %%>
5 |
6 |
<%= filepath.Base(tx.DB().Path()) %>
7 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | default: build
2 |
3 | build: templates
4 | mkdir -p bin
5 | go build -o bin/boltd ./cmd/boltd
6 |
7 | # go get github.com/benbjohnson/ego/...
8 | templates:
9 | @ego .
10 |
11 | .PHONY: templates
12 |
--------------------------------------------------------------------------------
/templates/index.ego:
--------------------------------------------------------------------------------
1 | <%! func Index(w io.Writer) error %>
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | redirecting...
10 |
11 |
--------------------------------------------------------------------------------
/templates/error.ego:
--------------------------------------------------------------------------------
1 | <%! func Error(w io.Writer, err error) error %>
2 |
3 |
4 |
5 |
6 |
7 | boltd
8 |
9 |
10 |
11 |
12 |
15 |
16 | An error has occurred: <%= err %>
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/templates/head.ego:
--------------------------------------------------------------------------------
1 | <%! func head(w io.Writer, tx *bolt.Tx) error %>
2 |
3 | <%% import "path/filepath" %%>
4 | <%% import "github.com/boltdb/bolt" %%>
5 |
6 |
7 |
8 | <%= filepath.Base(tx.DB().Path()) %>
9 |
10 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | boltd 
2 | =====
3 |
4 | This server allows you introspect Bolt database in a web browser. The boltd tool
5 | gives you access to low-level page information and b-tree structures so you can
6 | better understand how Bolt is laying out your data.
7 |
8 |
9 | ## Getting Started
10 |
11 | To install boltd, use the `go get` command:
12 |
13 | ```sh
14 | $ go get github.com/boltdb/boltd/...
15 | ```
16 |
17 | And then run the `boltd` binary by passing in the path to your database:
18 |
19 | ```sh
20 | $ boltd path/to/my.db
21 | ```
22 |
23 |
24 | ## HTTP Integration
25 |
26 | You can also use boltd as an `http.Handler` in your own application. To use it,
27 | simply add the handler to your muxer:
28 |
29 | ```go
30 | http.Handle("/introspect", http.StripPrefix("/introspect", boltd.NewHandler(mydb)))
31 | ```
32 |
--------------------------------------------------------------------------------
/cmd/boltd/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net/http"
8 |
9 | "github.com/boltdb/bolt"
10 | "github.com/boltdb/boltd"
11 | )
12 |
13 | func main() {
14 | log.SetFlags(0)
15 | var (
16 | addr = flag.String("addr", ":9000", "bind address")
17 | )
18 | flag.Parse()
19 |
20 | // Validate parameters.
21 | var path = flag.Arg(0)
22 | if path == "" {
23 | log.Fatal("path required")
24 | }
25 |
26 | // Open the database.
27 | db, err := bolt.Open(path, 0600, nil)
28 | if err != nil {
29 | log.Fatal(err)
30 | }
31 |
32 | // Enable logging.
33 | log.SetFlags(log.LstdFlags)
34 |
35 | // Setup the HTTP handlers.
36 | http.Handle("/", boltd.NewHandler(db))
37 |
38 | // Start the HTTP server.
39 | go func() { log.Fatal(http.ListenAndServe(*addr, nil)) }()
40 |
41 | fmt.Printf("Listening on http://localhost%s\n", *addr)
42 | select {}
43 | }
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Ben Johnson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/handler.go:
--------------------------------------------------------------------------------
1 | package boltd
2 |
3 | import (
4 | "net/http"
5 | "strconv"
6 | "strings"
7 |
8 | "github.com/boltdb/bolt"
9 | "github.com/boltdb/boltd/templates"
10 | )
11 |
12 | // NewHandler returns a new root HTTP handler.
13 | func NewHandler(db *bolt.DB) http.Handler {
14 | h := &handler{db}
15 | mux := http.NewServeMux()
16 | mux.HandleFunc("/", h.index)
17 | mux.HandleFunc("/page", h.page)
18 | return mux
19 | }
20 |
21 | type handler struct {
22 | db *bolt.DB
23 | }
24 |
25 | func (h *handler) index(w http.ResponseWriter, r *http.Request) {
26 | templates.Index(w)
27 | }
28 |
29 | func (h *handler) page(w http.ResponseWriter, r *http.Request) {
30 | err := h.db.View(func(tx *bolt.Tx) error {
31 | showUsage := (r.FormValue("usage") == "true")
32 |
33 | // Use the direct page id, if available.
34 | if r.FormValue("id") != "" {
35 | id, _ := strconv.Atoi(r.FormValue("id"))
36 | return templates.Page(w, r, tx, nil, id, showUsage)
37 | }
38 |
39 | // Otherwise extract the indexes and traverse.
40 | indexes, err := indexes(r)
41 | if err != nil {
42 | return err
43 | }
44 |
45 | return templates.Page(w, r, tx, indexes, 0, showUsage)
46 | })
47 | if err != nil {
48 | templates.Error(w, err)
49 | }
50 | }
51 |
52 | // parses and returns all indexes from a request.
53 | func indexes(r *http.Request) ([]int, error) {
54 | var a = []int{0}
55 | if len(r.FormValue("index")) > 0 {
56 | for _, s := range strings.Split(r.FormValue("index"), ":") {
57 | i, err := strconv.Atoi(s)
58 | if err != nil {
59 | return nil, err
60 | }
61 | a = append(a, i)
62 | }
63 | }
64 | return a, nil
65 | }
66 |
--------------------------------------------------------------------------------
/templates/templates.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import (
4 | "fmt"
5 | "math"
6 | "sort"
7 | "strconv"
8 | "strings"
9 | "unicode"
10 | "unicode/utf8"
11 | "unsafe"
12 |
13 | "github.com/boltdb/bolt"
14 | )
15 |
16 | // tostr converts a byte slice to a string if all characters are printable.
17 | // otherwise prints the hex representation.
18 | func tostr(b []byte) string {
19 | // Check if byte slice is utf-8 encoded.
20 | if !utf8.Valid(b) {
21 | return fmt.Sprintf("%x", b)
22 | }
23 |
24 | // Check every rune to see if it's printable.
25 | var s = string(b)
26 | for _, ch := range s {
27 | if !unicode.IsPrint(ch) {
28 | return fmt.Sprintf("%x", b)
29 | }
30 | }
31 |
32 | return s
33 | }
34 |
35 | func trunc(s string, n int) string {
36 | if len(s) > n {
37 | return s[:n] + "..."
38 | }
39 | return s
40 | }
41 |
42 | // traverses the page hierarchy by index and returns associated page ids.
43 | // returns an error if an index is out of range.
44 | func pgids(t *bolt.Tx, indexes []int) ([]pgid, error) {
45 | tx := (*tx)(unsafe.Pointer(t))
46 |
47 | p := pageAt(t, tx.meta.root.root)
48 | ids := []pgid{tx.meta.root.root}
49 | for _, index := range indexes[1:] {
50 | if uint16(index) >= p.count {
51 | return nil, fmt.Errorf("out of range")
52 | }
53 |
54 | if (p.flags & branchPageFlag) != 0 {
55 | e := p.branchPageElement(uint16(index))
56 | ids = append(ids, e.pgid)
57 | p = pageAt(t, e.pgid)
58 |
59 | } else if (p.flags & leafPageFlag) != 0 {
60 | // Only non-inline buckets on leaf pages can be traversed.
61 | e := p.leafPageElement(uint16(index))
62 | if (e.flags & bucketLeafFlag) == 0 {
63 | return nil, fmt.Errorf("index not a bucket")
64 | }
65 |
66 | b := (*bucket)(unsafe.Pointer(&e.value()[0]))
67 | if (e.flags & bucketLeafFlag) == 0 {
68 | return nil, fmt.Errorf("index is an inline bucket")
69 | }
70 |
71 | ids = append(ids, b.root)
72 | p = pageAt(t, b.root)
73 | } else {
74 | return nil, fmt.Errorf("invalid page type: %s" + p.typ())
75 | }
76 | }
77 | return ids, nil
78 | }
79 |
80 | func pagelink(indexes []int) string {
81 | var a []string
82 | for _, index := range indexes[1:] {
83 | a = append(a, strconv.Itoa(index))
84 | }
85 | return "page?index=" + strings.Join(a, ":")
86 | }
87 |
88 | func subpagelink(indexes []int, index int) string {
89 | var tmp = make([]int, len(indexes))
90 | copy(tmp, indexes)
91 | tmp = append(tmp, index)
92 | return pagelink(tmp)
93 | }
94 |
95 | // borrowed from: https://github.com/dustin/go-humanize
96 | func comma(v int) string {
97 | sign := ""
98 | if v < 0 {
99 | sign = "-"
100 | v = 0 - v
101 | }
102 |
103 | parts := []string{"", "", "", "", "", "", "", ""}
104 | j := len(parts) - 1
105 |
106 | for v > 999 {
107 | parts[j] = strconv.FormatInt(int64(v)%1000, 10)
108 | switch len(parts[j]) {
109 | case 2:
110 | parts[j] = "0" + parts[j]
111 | case 1:
112 | parts[j] = "00" + parts[j]
113 | }
114 | v = v / 1000
115 | j--
116 | }
117 | parts[j] = strconv.Itoa(int(v))
118 | return sign + strings.Join(parts[j:len(parts)], ",")
119 | }
120 |
121 | // maxHistogramN is the maximum number of buckets that can be used for the histogram.
122 | const maxHistogramN = 100
123 |
124 | // bucketize converts a map of observations into a histogram with a
125 | // smaller set of buckets using the square root choice method.
126 | func bucketize(m map[int]int) (mins, maxs, values []int) {
127 | if len(m) == 0 {
128 | return nil, nil, nil
129 | } else if len(m) == 1 {
130 | for k, v := range m {
131 | return []int{k}, []int{k}, []int{v}
132 | }
133 | }
134 |
135 | // Retrieve sorted set of keys.
136 | var keys []int
137 | var vsum int
138 | for k, v := range m {
139 | keys = append(keys, k)
140 | vsum += v
141 | }
142 | sort.Ints(keys)
143 |
144 | // Determine min/max for 5-95 percentile.
145 | var pmin, pmax, x int
146 | for _, k := range keys {
147 | v := m[k]
148 |
149 | // Grab the min when we cross the 5% threshold and 95% threshold.
150 | if (x*100)/vsum < 5 && ((x+v)*100)/vsum >= 5 {
151 | pmin = k
152 | }
153 | if (x*100)/vsum < 95 && ((x+v)*100)/vsum >= 95 {
154 | pmax = k
155 | }
156 |
157 | x += m[k]
158 | }
159 | min, max := keys[0], keys[len(keys)-1]
160 |
161 | // Calculate number of buckets and step size.
162 | n := int(math.Ceil(math.Sqrt(float64(vsum))))
163 | if n > maxHistogramN {
164 | n = maxHistogramN
165 | }
166 | step := float64(pmax-pmin) / float64(n)
167 |
168 | // Bucket everything.
169 | for i := 0; i < n; i++ {
170 | var kmin, kmax int
171 | if i == 0 {
172 | kmin = min
173 | } else {
174 | kmin = int(math.Floor(float64(pmin) + step*float64(i)))
175 | }
176 | if i == n-1 {
177 | kmax = max
178 | } else {
179 | kmax = int(math.Floor(float64(pmin)+step*float64(i+1))) - 1
180 | }
181 | value := 0
182 |
183 | for k, v := range m {
184 | if (i == 0 || k >= kmin) && (i == (n-1) || k <= kmax) {
185 | value += v
186 | }
187 | }
188 |
189 | mins = append(mins, kmin)
190 | maxs = append(maxs, kmax)
191 | values = append(values, value)
192 | }
193 |
194 | return
195 | }
196 |
--------------------------------------------------------------------------------
/templates/page.ego:
--------------------------------------------------------------------------------
1 | <%! func Page(w io.Writer, r *http.Request, tx *bolt.Tx, indexes []int, directID int, showUsage bool) error %>
2 |
3 | <%% import "net/http" %%>
4 | <%% import "strings" %%>
5 | <%% import "unsafe" %%>
6 | <%% import "github.com/boltdb/bolt" %%>
7 |
8 | <%
9 | p, ids, err := find(tx, directID, indexes)
10 | if err != nil {
11 | return err
12 | }
13 |
14 | // Generate page stats.
15 | pageSize := tx.DB().Info().PageSize
16 | stats := p.stats(pageSize)
17 |
18 | // Generate histogram of all nested page usage.
19 | var histogram map[int]int
20 | if showUsage {
21 | histogram = usage(tx, p.id)
22 | }
23 | %>
24 |
25 |
26 |
27 | <% head(w, tx) %>
28 |
29 |
30 | <% nav(w, tx) %>
31 |
32 |
33 | <% for i, id := range ids { %>
34 | <% if i > 0 { %>»<% } %>
35 | #<%= id %>
36 | <% } %>
37 |
38 |
39 | Page Information
40 |
41 | ID: <%= comma(int(p.id)) %>
42 | Type: <%= fmt.Sprintf("%s (%x)", p.typ(), p.flags) %>
43 | Overflow: <%= p.overflow %>
44 |
45 | Alloc: <%= comma(stats.alloc) %>
46 | In Use: <%= comma(stats.inuse) %>
47 | Utilization: <%= fmt.Sprintf("%.2f%%", stats.utilization*100) %>
48 |
49 |
50 | <% if (p.flags & branchPageFlag) != 0 { %>
51 | Branch Elements (<%= p.count %>)
52 |
53 |
54 |
55 | | Key |
56 | Page ID |
57 | Size (k) |
58 | %%Util |
59 |
60 |
61 |
62 | <% for i := uint16(0); i < p.count; i++ { %>
63 | <% e := p.branchPageElement(i) %>
64 | <% subpage := pageAt(tx, e.pgid) %>
65 | <% substats := subpage.stats(pageSize) %>
66 |
67 | | <%= trunc(tostr(e.key()), 40) %> |
68 | <%= e.pgid %> |
69 | <%= len(e.key()) %> |
70 | <%= fmt.Sprintf("%.2f%%", substats.utilization*100) %> |
71 |
72 | <% } %>
73 |
74 |
75 |
76 | <% } else if (p.flags & leafPageFlag) != 0 { %>
77 | Leaf Elements (<%= p.count %>)
78 |
79 |
80 |
81 | | Key |
82 | Value |
83 | Size (k/v) |
84 | %%Util |
85 |
86 |
87 |
88 | <% for i := uint16(0); i < p.count; i++ { %>
89 | <% e := p.leafPageElement(i) %>
90 | <% if (e.flags & bucketLeafFlag) != 0 { %>
91 | <% b := ((*bucket)(unsafe.Pointer(&e.value()[0]))) %>
92 | <%
93 | util := "-"
94 | if b.root != 0 {
95 | substats := pageAt(tx, b.root).stats(pageSize)
96 | util = fmt.Sprintf("%.2f%%", substats.utilization*100)
97 | }
98 | %>
99 |
100 | | <%= trunc(tostr(e.key()), 40) %> |
101 |
102 | <bucket(root=<% if b.root != 0 { %><% } %><%= b.root %><% if b.root != 0 { %><% } %>; seq=<%= b.sequence %>)>
103 | |
104 | <%= len(e.key()) %> / <%= len(e.value()) %> |
105 | <%= util %> |
106 |
107 | <% } else { %>
108 |
109 | | <%= trunc(tostr(e.key()), 40) %> |
110 | <%= trunc(tostr(e.value()), 40) %> |
111 | <%= len(e.key()) %> / <%= len(e.value()) %> |
112 | |
113 |
114 | <% } %>
115 | <% } %>
116 |
117 |
118 | <% } %>
119 |
120 | <% if showUsage { %>
121 | <%
122 | mins, maxs, values := bucketize(histogram)
123 | vmax, maxlen := 0, 20
124 | for _, v := range values {
125 | if v > vmax {
126 | vmax = v
127 | }
128 | }
129 | %>
130 |
131 | Page Usage Histogram
132 |
133 |
134 |
135 | | Usage (bytes) |
136 | Count |
137 | |
138 |
139 |
140 |
141 | <% for i := 0; i < len(values); i++ { %>
142 |
143 | | <%= mins[i] %> - <%= maxs[i] %>
144 | | <%= values[i] %>
145 | | <%= strings.Repeat("█", int((float64(values[i])/float64(vmax))*float64(maxlen))) %> |
146 |
147 | <% } %>
148 |
149 |
150 | <% } else { %>
151 | <%
152 | u, q := r.URL, r.URL.Query()
153 | q.Set("usage", "true")
154 | u.RawQuery = q.Encode()
155 | %>
156 |
157 | Show Page Usage
158 | <% } %>
159 |
160 |
161 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/templates/bolt.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | // This file contains low-level bolt structs that are used for reading from
4 | // bolt database files.
5 |
6 | import (
7 | "fmt"
8 | "unsafe"
9 |
10 | "github.com/boltdb/bolt"
11 | )
12 |
13 | const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr))
14 | const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{}))
15 | const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{}))
16 |
17 | const maxAllocSize = 0xFFFFFFF
18 | const maxNodesPerPage = 65535
19 |
20 | const (
21 | branchPageFlag = 0x01
22 | leafPageFlag = 0x02
23 | metaPageFlag = 0x04
24 | freelistPageFlag = 0x10
25 | )
26 |
27 | const (
28 | bucketLeafFlag = 0x01
29 | )
30 |
31 | type pgid uint64
32 | type txid uint64
33 |
34 | type page struct {
35 | id pgid
36 | flags uint16
37 | count uint16
38 | overflow uint32
39 | ptr uintptr
40 | }
41 |
42 | type stats struct {
43 | inuse int
44 | alloc int
45 | utilization float64
46 | histogram map[int]int
47 | }
48 |
49 | // typ returns a human readable page type string used for debugging.
50 | func (p *page) typ() string {
51 | if (p.flags & branchPageFlag) != 0 {
52 | return "branch"
53 | } else if (p.flags & leafPageFlag) != 0 {
54 | return "leaf"
55 | } else if (p.flags & metaPageFlag) != 0 {
56 | return "meta"
57 | } else if (p.flags & freelistPageFlag) != 0 {
58 | return "freelist"
59 | }
60 | return fmt.Sprintf("unknown<%02x>", p.flags)
61 | }
62 |
63 | func (p *page) meta() *meta {
64 | return (*meta)(unsafe.Pointer(&p.ptr))
65 | }
66 |
67 | func (p *page) leafPageElement(index uint16) *leafPageElement {
68 | n := &((*[maxNodesPerPage]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
69 | return n
70 | }
71 |
72 | func (p *page) branchPageElement(index uint16) *branchPageElement {
73 | return &((*[maxNodesPerPage]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
74 | }
75 |
76 | // stats calcuates statistics for a page.
77 | func (p *page) stats(pageSize int) stats {
78 | var s stats
79 | s.alloc = (int(p.overflow) + 1) * pageSize
80 | s.inuse = p.inuse()
81 |
82 | // Calculate space utilitization
83 | if s.alloc > 0 {
84 | s.utilization = float64(s.inuse) / float64(s.alloc)
85 | }
86 |
87 | return s
88 | }
89 |
90 | // inuse returns the number of bytes used in a given page.
91 | func (p *page) inuse() int {
92 | var n int
93 | if (p.flags & leafPageFlag) != 0 {
94 | n = pageHeaderSize
95 | if p.count > 0 {
96 | n += leafPageElementSize * int(p.count-1)
97 | e := p.leafPageElement(p.count - 1)
98 | n += int(e.pos + e.ksize + e.vsize)
99 | }
100 |
101 | } else if (p.flags & branchPageFlag) != 0 {
102 | n = pageHeaderSize
103 | if p.count > 0 {
104 | n += branchPageElementSize * int(p.count-1)
105 | e := p.branchPageElement(p.count - 1)
106 | n += int(e.pos + e.ksize)
107 | }
108 | }
109 | return n
110 | }
111 |
112 | // usage calculates a histogram of page sizes within nested pages.
113 | func usage(tx *bolt.Tx, pgid pgid) map[int]int {
114 | m := make(map[int]int)
115 | forEachPage(tx, pgid, func(p *page) {
116 | m[p.inuse()]++
117 | })
118 | return m
119 | }
120 |
121 | // branchPageElement represents a node on a branch page.
122 | type branchPageElement struct {
123 | pos uint32
124 | ksize uint32
125 | pgid pgid
126 | }
127 |
128 | // key returns a byte slice of the node key.
129 | func (n *branchPageElement) key() []byte {
130 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
131 | return buf[n.pos : n.pos+n.ksize]
132 | }
133 |
134 | // leafPageElement represents a node on a leaf page.
135 | type leafPageElement struct {
136 | flags uint32
137 | pos uint32
138 | ksize uint32
139 | vsize uint32
140 | }
141 |
142 | // key returns a byte slice of the node key.
143 | func (n *leafPageElement) key() []byte {
144 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
145 | return buf[n.pos : n.pos+n.ksize]
146 | }
147 |
148 | // value returns a byte slice of the node value.
149 | func (n *leafPageElement) value() []byte {
150 | buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
151 | return buf[n.pos+n.ksize : n.pos+n.ksize+n.vsize]
152 | }
153 |
154 | type meta struct {
155 | magic uint32
156 | version uint32
157 | pageSize uint32
158 | flags uint32
159 | root bucket
160 | freelist pgid
161 | pgid pgid
162 | txid txid
163 | checksum uint64
164 | }
165 |
166 | // bucket_ represents the bolt.Bucket type.
167 | type bucket_ struct {
168 | *bucket
169 | }
170 |
171 | type bucket struct {
172 | root pgid
173 | sequence uint64
174 | }
175 |
176 | type tx struct {
177 | writable bool
178 | managed bool
179 | db uintptr
180 | meta *meta
181 | root bucket
182 | // remaining fields not used.
183 | }
184 |
185 | // find locates a page using either a set of page indices or a direct page id.
186 | // It returns a list of parent page numbers if the indices are used.
187 | // It also returns the page reference.
188 | func find(tx *bolt.Tx, directID int, indexes []int) (*page, []pgid, error) {
189 | // If a direct ID is provided then just use it.
190 | if directID != 0 {
191 | return pageAt(tx, pgid(directID)), nil, nil
192 | }
193 |
194 | // Otherwise traverse the pages index.
195 | ids, err := pgids(tx, indexes)
196 | if err != nil {
197 | return nil, nil, err
198 | }
199 |
200 | return pageAt(tx, ids[len(ids)-1]), ids, nil
201 | }
202 |
203 | // retrieves the page from a given transaction.
204 | func pageAt(tx *bolt.Tx, id pgid) *page {
205 | info := tx.DB().Info()
206 | return (*page)(unsafe.Pointer(info.Data + uintptr(info.PageSize*int(id))))
207 | }
208 |
209 | // forEachPage recursively iterates over all pages starting at a given page.
210 | func forEachPage(tx *bolt.Tx, pgid pgid, fn func(*page)) {
211 | p := pageAt(tx, pgid)
212 | fn(p)
213 |
214 | if (p.flags & leafPageFlag) != 0 {
215 | for i := 0; i < int(p.count); i++ {
216 | if e := p.leafPageElement(uint16(i)); (e.flags & bucketLeafFlag) != 0 {
217 | if b := (*bucket)(unsafe.Pointer(&e.value()[0])); b.root != 0 {
218 | forEachPage(tx, b.root, fn)
219 | }
220 | }
221 | }
222 | } else if (p.flags & branchPageFlag) != 0 {
223 | for i := 0; i < int(p.count); i++ {
224 | forEachPage(tx, p.branchPageElement(uint16(i)).pgid, fn)
225 | }
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/templates/ego.go:
--------------------------------------------------------------------------------
1 | package templates
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "net/http"
7 | "path/filepath"
8 | "strings"
9 | "unsafe"
10 |
11 | "github.com/boltdb/bolt"
12 | )
13 |
14 | //line error.ego:1
15 | func Error(w io.Writer, err error) error {
16 | //line error.ego:2
17 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
18 | return err
19 | }
20 | //line error.ego:3
21 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
22 | return err
23 | }
24 | //line error.ego:4
25 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
26 | return err
27 | }
28 | //line error.ego:5
29 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
30 | return err
31 | }
32 | //line error.ego:6
33 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
34 | return err
35 | }
36 | //line error.ego:7
37 | if _, err := fmt.Fprintf(w, "boltd"); err != nil {
38 | return err
39 | }
40 | //line error.ego:7
41 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
42 | return err
43 | }
44 | //line error.ego:8
45 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
46 | return err
47 | }
48 | //line error.ego:10
49 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
50 | return err
51 | }
52 | //line error.ego:11
53 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
54 | return err
55 | }
56 | //line error.ego:12
57 | if _, err := fmt.Fprintf(w, "\n\n An error has occurred: "); err != nil {
70 | return err
71 | }
72 | //line error.ego:16
73 | if _, err := fmt.Fprintf(w, "%v", err); err != nil {
74 | return err
75 | }
76 | //line error.ego:17
77 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
78 | return err
79 | }
80 | //line error.ego:17
81 | if _, err := fmt.Fprintf(w, "
"); err != nil {
82 | return err
83 | }
84 | //line error.ego:17
85 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
86 | return err
87 | }
88 | //line error.ego:18
89 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
90 | return err
91 | }
92 | //line error.ego:19
93 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
94 | return err
95 | }
96 | return nil
97 | }
98 |
99 | //line head.ego:1
100 | func head(w io.Writer, tx *bolt.Tx) error {
101 | //line head.ego:2
102 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
103 | return err
104 | }
105 | //line head.ego:4
106 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
107 | return err
108 | }
109 | //line head.ego:5
110 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
111 | return err
112 | }
113 | //line head.ego:6
114 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
115 | return err
116 | }
117 | //line head.ego:7
118 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
119 | return err
120 | }
121 | //line head.ego:8
122 | if _, err := fmt.Fprintf(w, ""); err != nil {
123 | return err
124 | }
125 | //line head.ego:8
126 | if _, err := fmt.Fprintf(w, "%v", filepath.Base(tx.DB().Path())); err != nil {
127 | return err
128 | }
129 | //line head.ego:8
130 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
131 | return err
132 | }
133 | //line head.ego:10
134 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
139 | return err
140 | }
141 | //line head.ego:24
142 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
143 | return err
144 | }
145 | return nil
146 | }
147 |
148 | //line index.ego:1
149 | func Index(w io.Writer) error {
150 | //line index.ego:2
151 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
152 | return err
153 | }
154 | //line index.ego:3
155 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
156 | return err
157 | }
158 | //line index.ego:4
159 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
160 | return err
161 | }
162 | //line index.ego:5
163 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
164 | return err
165 | }
166 | //line index.ego:6
167 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
168 | return err
169 | }
170 | //line index.ego:7
171 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
172 | return err
173 | }
174 | //line index.ego:9
175 | if _, err := fmt.Fprintf(w, "redirecting..."); err != nil {
176 | return err
177 | }
178 | //line index.ego:9
179 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
180 | return err
181 | }
182 | //line index.ego:10
183 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
184 | return err
185 | }
186 | return nil
187 | }
188 |
189 | //line nav.ego:1
190 | func nav(w io.Writer, tx *bolt.Tx) error {
191 | //line nav.ego:2
192 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
193 | return err
194 | }
195 | //line nav.ego:4
196 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
197 | return err
198 | }
199 | //line nav.ego:5
200 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
201 | return err
202 | }
203 | //line nav.ego:6
204 | if _, err := fmt.Fprintf(w, ""); err != nil {
205 | return err
206 | }
207 | //line nav.ego:6
208 | if _, err := fmt.Fprintf(w, "%v", filepath.Base(tx.DB().Path())); err != nil {
209 | return err
210 | }
211 | //line nav.ego:6
212 | if _, err := fmt.Fprintf(w, "
\n"); err != nil {
213 | return err
214 | }
215 | return nil
216 | }
217 |
218 | //line page.ego:1
219 | func Page(w io.Writer, r *http.Request, tx *bolt.Tx, indexes []int, directID int, showUsage bool) error {
220 | //line page.ego:2
221 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
222 | return err
223 | }
224 | //line page.ego:4
225 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
226 | return err
227 | }
228 | //line page.ego:5
229 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
230 | return err
231 | }
232 | //line page.ego:6
233 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
234 | return err
235 | }
236 | //line page.ego:7
237 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
238 | return err
239 | }
240 | //line page.ego:9
241 | p, ids, err := find(tx, directID, indexes)
242 | if err != nil {
243 | return err
244 | }
245 |
246 | // Generate page stats.
247 | pageSize := tx.DB().Info().PageSize
248 | stats := p.stats(pageSize)
249 |
250 | // Generate histogram of all nested page usage.
251 | var histogram map[int]int
252 | if showUsage {
253 | histogram = usage(tx, p.id)
254 | }
255 |
256 | //line page.ego:25
257 | if _, err := fmt.Fprintf(w, "\n\n"); err != nil {
258 | return err
259 | }
260 | //line page.ego:26
261 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
262 | return err
263 | }
264 | //line page.ego:27
265 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
266 | return err
267 | }
268 | //line page.ego:28
269 | head(w, tx)
270 | //line page.ego:29
271 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
272 | return err
273 | }
274 | //line page.ego:30
275 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
276 | return err
277 | }
278 | //line page.ego:31
279 | nav(w, tx)
280 | //line page.ego:32
281 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
282 | return err
283 | }
284 | //line page.ego:33
285 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
286 | return err
287 | }
288 | //line page.ego:34
289 | for i, id := range ids {
290 | //line page.ego:35
291 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
292 | return err
293 | }
294 | //line page.ego:35
295 | if i > 0 {
296 | //line page.ego:35
297 | if _, err := fmt.Fprintf(w, "»"); err != nil {
298 | return err
299 | }
300 | //line page.ego:35
301 | }
302 | //line page.ego:36
303 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
304 | return err
305 | }
306 | //line page.ego:36
307 | if _, err := fmt.Fprintf(w, "#"); err != nil {
316 | return err
317 | }
318 | //line page.ego:36
319 | if _, err := fmt.Fprintf(w, "%v", id); err != nil {
320 | return err
321 | }
322 | //line page.ego:36
323 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
324 | return err
325 | }
326 | //line page.ego:37
327 | }
328 | //line page.ego:38
329 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
330 | return err
331 | }
332 | //line page.ego:38
333 | if _, err := fmt.Fprintf(w, "
\n\n "); err != nil {
334 | return err
335 | }
336 | //line page.ego:40
337 | if _, err := fmt.Fprintf(w, "Page Information"); err != nil {
338 | return err
339 | }
340 | //line page.ego:40
341 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
342 | return err
343 | }
344 | //line page.ego:41
345 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
346 | return err
347 | }
348 | //line page.ego:42
349 | if _, err := fmt.Fprintf(w, "ID:"); err != nil {
350 | return err
351 | }
352 | //line page.ego:42
353 | if _, err := fmt.Fprintf(w, " "); err != nil {
354 | return err
355 | }
356 | //line page.ego:42
357 | if _, err := fmt.Fprintf(w, "%v", comma(int(p.id))); err != nil {
358 | return err
359 | }
360 | //line page.ego:42
361 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
362 | return err
363 | }
364 | //line page.ego:43
365 | if _, err := fmt.Fprintf(w, "Type:"); err != nil {
366 | return err
367 | }
368 | //line page.ego:43
369 | if _, err := fmt.Fprintf(w, " "); err != nil {
370 | return err
371 | }
372 | //line page.ego:43
373 | if _, err := fmt.Fprintf(w, "%v", fmt.Sprintf("%s (%x)", p.typ(), p.flags)); err != nil {
374 | return err
375 | }
376 | //line page.ego:43
377 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
378 | return err
379 | }
380 | //line page.ego:44
381 | if _, err := fmt.Fprintf(w, "Overflow:"); err != nil {
382 | return err
383 | }
384 | //line page.ego:44
385 | if _, err := fmt.Fprintf(w, " "); err != nil {
386 | return err
387 | }
388 | //line page.ego:44
389 | if _, err := fmt.Fprintf(w, "%v", p.overflow); err != nil {
390 | return err
391 | }
392 | //line page.ego:44
393 | if _, err := fmt.Fprintf(w, "
"); err != nil {
394 | return err
395 | }
396 | //line page.ego:44
397 | if _, err := fmt.Fprintf(w, "
\n\n "); err != nil {
398 | return err
399 | }
400 | //line page.ego:46
401 | if _, err := fmt.Fprintf(w, "Alloc:"); err != nil {
402 | return err
403 | }
404 | //line page.ego:46
405 | if _, err := fmt.Fprintf(w, " "); err != nil {
406 | return err
407 | }
408 | //line page.ego:46
409 | if _, err := fmt.Fprintf(w, "%v", comma(stats.alloc)); err != nil {
410 | return err
411 | }
412 | //line page.ego:46
413 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
414 | return err
415 | }
416 | //line page.ego:47
417 | if _, err := fmt.Fprintf(w, "In Use:"); err != nil {
418 | return err
419 | }
420 | //line page.ego:47
421 | if _, err := fmt.Fprintf(w, " "); err != nil {
422 | return err
423 | }
424 | //line page.ego:47
425 | if _, err := fmt.Fprintf(w, "%v", comma(stats.inuse)); err != nil {
426 | return err
427 | }
428 | //line page.ego:47
429 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
430 | return err
431 | }
432 | //line page.ego:48
433 | if _, err := fmt.Fprintf(w, "Utilization:"); err != nil {
434 | return err
435 | }
436 | //line page.ego:48
437 | if _, err := fmt.Fprintf(w, " "); err != nil {
438 | return err
439 | }
440 | //line page.ego:48
441 | if _, err := fmt.Fprintf(w, "%v", fmt.Sprintf("%.2f%%", stats.utilization*100)); err != nil {
442 | return err
443 | }
444 | //line page.ego:48
445 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
446 | return err
447 | }
448 | //line page.ego:49
449 | if _, err := fmt.Fprintf(w, "
\n\n "); err != nil {
450 | return err
451 | }
452 | //line page.ego:51
453 | if (p.flags & branchPageFlag) != 0 {
454 | //line page.ego:52
455 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
456 | return err
457 | }
458 | //line page.ego:52
459 | if _, err := fmt.Fprintf(w, "Branch Elements ("); err != nil {
460 | return err
461 | }
462 | //line page.ego:52
463 | if _, err := fmt.Fprintf(w, "%v", p.count); err != nil {
464 | return err
465 | }
466 | //line page.ego:52
467 | if _, err := fmt.Fprintf(w, ")"); err != nil {
468 | return err
469 | }
470 | //line page.ego:52
471 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
472 | return err
473 | }
474 | //line page.ego:53
475 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
476 | return err
477 | }
478 | //line page.ego:54
479 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
480 | return err
481 | }
482 | //line page.ego:55
483 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
484 | return err
485 | }
486 | //line page.ego:56
487 | if _, err := fmt.Fprintf(w, "| Key"); err != nil {
488 | return err
489 | }
490 | //line page.ego:56
491 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
492 | return err
493 | }
494 | //line page.ego:57
495 | if _, err := fmt.Fprintf(w, "Page ID"); err != nil {
496 | return err
497 | }
498 | //line page.ego:57
499 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
500 | return err
501 | }
502 | //line page.ego:58
503 | if _, err := fmt.Fprintf(w, "Size (k)"); err != nil {
504 | return err
505 | }
506 | //line page.ego:58
507 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
508 | return err
509 | }
510 | //line page.ego:59
511 | if _, err := fmt.Fprintf(w, "%%Util"); err != nil {
512 | return err
513 | }
514 | //line page.ego:59
515 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
516 | return err
517 | }
518 | //line page.ego:60
519 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
520 | return err
521 | }
522 | //line page.ego:61
523 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
524 | return err
525 | }
526 | //line page.ego:62
527 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
528 | return err
529 | }
530 | //line page.ego:63
531 | for i := uint16(0); i < p.count; i++ {
532 | //line page.ego:64
533 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
534 | return err
535 | }
536 | //line page.ego:64
537 | e := p.branchPageElement(i)
538 | //line page.ego:65
539 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
540 | return err
541 | }
542 | //line page.ego:65
543 | subpage := pageAt(tx, e.pgid)
544 | //line page.ego:66
545 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
546 | return err
547 | }
548 | //line page.ego:66
549 | substats := subpage.stats(pageSize)
550 | //line page.ego:67
551 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
552 | return err
553 | }
554 | //line page.ego:67
555 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
556 | return err
557 | }
558 | //line page.ego:68
559 | if _, err := fmt.Fprintf(w, "| "); err != nil {
560 | return err
561 | }
562 | //line page.ego:68
563 | if _, err := fmt.Fprintf(w, "%v", trunc(tostr(e.key()), 40)); err != nil {
564 | return err
565 | }
566 | //line page.ego:68
567 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
568 | return err
569 | }
570 | //line page.ego:69
571 | if _, err := fmt.Fprintf(w, ""); err != nil {
572 | return err
573 | }
574 | //line page.ego:69
575 | if _, err := fmt.Fprintf(w, ""); err != nil {
584 | return err
585 | }
586 | //line page.ego:69
587 | if _, err := fmt.Fprintf(w, "%v", e.pgid); err != nil {
588 | return err
589 | }
590 | //line page.ego:69
591 | if _, err := fmt.Fprintf(w, ""); err != nil {
592 | return err
593 | }
594 | //line page.ego:69
595 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
596 | return err
597 | }
598 | //line page.ego:70
599 | if _, err := fmt.Fprintf(w, ""); err != nil {
600 | return err
601 | }
602 | //line page.ego:70
603 | if _, err := fmt.Fprintf(w, "%v", len(e.key())); err != nil {
604 | return err
605 | }
606 | //line page.ego:70
607 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
608 | return err
609 | }
610 | //line page.ego:71
611 | if _, err := fmt.Fprintf(w, ""); err != nil {
612 | return err
613 | }
614 | //line page.ego:71
615 | if _, err := fmt.Fprintf(w, "%v", fmt.Sprintf("%.2f%%", substats.utilization*100)); err != nil {
616 | return err
617 | }
618 | //line page.ego:71
619 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
620 | return err
621 | }
622 | //line page.ego:72
623 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
624 | return err
625 | }
626 | //line page.ego:73
627 | }
628 | //line page.ego:74
629 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
630 | return err
631 | }
632 | //line page.ego:74
633 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
634 | return err
635 | }
636 | //line page.ego:75
637 | if _, err := fmt.Fprintf(w, "
\n \n "); err != nil {
638 | return err
639 | }
640 | //line page.ego:77
641 | } else if (p.flags & leafPageFlag) != 0 {
642 | //line page.ego:78
643 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
644 | return err
645 | }
646 | //line page.ego:78
647 | if _, err := fmt.Fprintf(w, "Leaf Elements ("); err != nil {
648 | return err
649 | }
650 | //line page.ego:78
651 | if _, err := fmt.Fprintf(w, "%v", p.count); err != nil {
652 | return err
653 | }
654 | //line page.ego:78
655 | if _, err := fmt.Fprintf(w, ")"); err != nil {
656 | return err
657 | }
658 | //line page.ego:78
659 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
660 | return err
661 | }
662 | //line page.ego:79
663 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
664 | return err
665 | }
666 | //line page.ego:80
667 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
668 | return err
669 | }
670 | //line page.ego:81
671 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
672 | return err
673 | }
674 | //line page.ego:82
675 | if _, err := fmt.Fprintf(w, "| Key"); err != nil {
676 | return err
677 | }
678 | //line page.ego:82
679 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
680 | return err
681 | }
682 | //line page.ego:83
683 | if _, err := fmt.Fprintf(w, "Value"); err != nil {
684 | return err
685 | }
686 | //line page.ego:83
687 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
688 | return err
689 | }
690 | //line page.ego:84
691 | if _, err := fmt.Fprintf(w, "Size (k/v)"); err != nil {
692 | return err
693 | }
694 | //line page.ego:84
695 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
696 | return err
697 | }
698 | //line page.ego:85
699 | if _, err := fmt.Fprintf(w, "%%Util"); err != nil {
700 | return err
701 | }
702 | //line page.ego:85
703 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
704 | return err
705 | }
706 | //line page.ego:86
707 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
708 | return err
709 | }
710 | //line page.ego:87
711 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
712 | return err
713 | }
714 | //line page.ego:88
715 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
716 | return err
717 | }
718 | //line page.ego:89
719 | for i := uint16(0); i < p.count; i++ {
720 | //line page.ego:90
721 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
722 | return err
723 | }
724 | //line page.ego:90
725 | e := p.leafPageElement(i)
726 | //line page.ego:91
727 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
728 | return err
729 | }
730 | //line page.ego:91
731 | if (e.flags & bucketLeafFlag) != 0 {
732 | //line page.ego:92
733 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
734 | return err
735 | }
736 | //line page.ego:92
737 | b := ((*bucket)(unsafe.Pointer(&e.value()[0])))
738 | //line page.ego:93
739 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
740 | return err
741 | }
742 | //line page.ego:94
743 | util := "-"
744 | if b.root != 0 {
745 | substats := pageAt(tx, b.root).stats(pageSize)
746 | util = fmt.Sprintf("%.2f%%", substats.utilization*100)
747 | }
748 |
749 | //line page.ego:101
750 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
751 | return err
752 | }
753 | //line page.ego:101
754 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
755 | return err
756 | }
757 | //line page.ego:102
758 | if _, err := fmt.Fprintf(w, "| "); err != nil {
759 | return err
760 | }
761 | //line page.ego:102
762 | if _, err := fmt.Fprintf(w, ""); err != nil {
763 | return err
764 | }
765 | //line page.ego:102
766 | if _, err := fmt.Fprintf(w, "%v", trunc(tostr(e.key()), 40)); err != nil {
767 | return err
768 | }
769 | //line page.ego:102
770 | if _, err := fmt.Fprintf(w, ""); err != nil {
771 | return err
772 | }
773 | //line page.ego:102
774 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
775 | return err
776 | }
777 | //line page.ego:103
778 | if _, err := fmt.Fprintf(w, "\n <bucket(root="); err != nil {
779 | return err
780 | }
781 | //line page.ego:104
782 | if b.root != 0 {
783 | //line page.ego:104
784 | if _, err := fmt.Fprintf(w, ""); err != nil {
793 | return err
794 | }
795 | //line page.ego:104
796 | }
797 | //line page.ego:104
798 | if _, err := fmt.Fprintf(w, "%v", b.root); err != nil {
799 | return err
800 | }
801 | //line page.ego:104
802 | if b.root != 0 {
803 | //line page.ego:104
804 | if _, err := fmt.Fprintf(w, ""); err != nil {
805 | return err
806 | }
807 | //line page.ego:104
808 | }
809 | //line page.ego:104
810 | if _, err := fmt.Fprintf(w, "; seq="); err != nil {
811 | return err
812 | }
813 | //line page.ego:104
814 | if _, err := fmt.Fprintf(w, "%v", b.sequence); err != nil {
815 | return err
816 | }
817 | //line page.ego:104
818 | if _, err := fmt.Fprintf(w, ">\n "); err != nil {
819 | return err
820 | }
821 | //line page.ego:105
822 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
823 | return err
824 | }
825 | //line page.ego:106
826 | if _, err := fmt.Fprintf(w, ""); err != nil {
827 | return err
828 | }
829 | //line page.ego:106
830 | if _, err := fmt.Fprintf(w, "%v", len(e.key())); err != nil {
831 | return err
832 | }
833 | //line page.ego:106
834 | if _, err := fmt.Fprintf(w, " / "); err != nil {
835 | return err
836 | }
837 | //line page.ego:106
838 | if _, err := fmt.Fprintf(w, "%v", len(e.value())); err != nil {
839 | return err
840 | }
841 | //line page.ego:106
842 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
843 | return err
844 | }
845 | //line page.ego:107
846 | if _, err := fmt.Fprintf(w, ""); err != nil {
847 | return err
848 | }
849 | //line page.ego:107
850 | if _, err := fmt.Fprintf(w, "%v", util); err != nil {
851 | return err
852 | }
853 | //line page.ego:107
854 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
855 | return err
856 | }
857 | //line page.ego:108
858 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
859 | return err
860 | }
861 | //line page.ego:109
862 | } else {
863 | //line page.ego:110
864 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
865 | return err
866 | }
867 | //line page.ego:110
868 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
869 | return err
870 | }
871 | //line page.ego:111
872 | if _, err := fmt.Fprintf(w, "| "); err != nil {
873 | return err
874 | }
875 | //line page.ego:111
876 | if _, err := fmt.Fprintf(w, "%v", trunc(tostr(e.key()), 40)); err != nil {
877 | return err
878 | }
879 | //line page.ego:111
880 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
881 | return err
882 | }
883 | //line page.ego:112
884 | if _, err := fmt.Fprintf(w, ""); err != nil {
885 | return err
886 | }
887 | //line page.ego:112
888 | if _, err := fmt.Fprintf(w, "%v", trunc(tostr(e.value()), 40)); err != nil {
889 | return err
890 | }
891 | //line page.ego:112
892 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
893 | return err
894 | }
895 | //line page.ego:113
896 | if _, err := fmt.Fprintf(w, ""); err != nil {
897 | return err
898 | }
899 | //line page.ego:113
900 | if _, err := fmt.Fprintf(w, "%v", len(e.key())); err != nil {
901 | return err
902 | }
903 | //line page.ego:113
904 | if _, err := fmt.Fprintf(w, " / "); err != nil {
905 | return err
906 | }
907 | //line page.ego:113
908 | if _, err := fmt.Fprintf(w, "%v", len(e.value())); err != nil {
909 | return err
910 | }
911 | //line page.ego:113
912 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
913 | return err
914 | }
915 | //line page.ego:114
916 | if _, err := fmt.Fprintf(w, " "); err != nil {
917 | return err
918 | }
919 | //line page.ego:114
920 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
921 | return err
922 | }
923 | //line page.ego:115
924 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
925 | return err
926 | }
927 | //line page.ego:116
928 | }
929 | //line page.ego:117
930 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
931 | return err
932 | }
933 | //line page.ego:117
934 | }
935 | //line page.ego:118
936 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
937 | return err
938 | }
939 | //line page.ego:118
940 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
941 | return err
942 | }
943 | //line page.ego:119
944 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
945 | return err
946 | }
947 | //line page.ego:120
948 | }
949 | //line page.ego:121
950 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
951 | return err
952 | }
953 | //line page.ego:122
954 | if showUsage {
955 | //line page.ego:123
956 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
957 | return err
958 | }
959 | //line page.ego:124
960 | mins, maxs, values := bucketize(histogram)
961 | vmax, maxlen := 0, 20
962 | for _, v := range values {
963 | if v > vmax {
964 | vmax = v
965 | }
966 | }
967 |
968 | //line page.ego:133
969 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
970 | return err
971 | }
972 | //line page.ego:134
973 | if _, err := fmt.Fprintf(w, "Page Usage Histogram"); err != nil {
974 | return err
975 | }
976 | //line page.ego:134
977 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
978 | return err
979 | }
980 | //line page.ego:135
981 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
982 | return err
983 | }
984 | //line page.ego:136
985 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
986 | return err
987 | }
988 | //line page.ego:137
989 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
990 | return err
991 | }
992 | //line page.ego:138
993 | if _, err := fmt.Fprintf(w, "| Usage (bytes)"); err != nil {
994 | return err
995 | }
996 | //line page.ego:138
997 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
998 | return err
999 | }
1000 | //line page.ego:139
1001 | if _, err := fmt.Fprintf(w, "Count"); err != nil {
1002 | return err
1003 | }
1004 | //line page.ego:139
1005 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
1006 | return err
1007 | }
1008 | //line page.ego:140
1009 | if _, err := fmt.Fprintf(w, " "); err != nil {
1010 | return err
1011 | }
1012 | //line page.ego:140
1013 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
1014 | return err
1015 | }
1016 | //line page.ego:141
1017 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
1018 | return err
1019 | }
1020 | //line page.ego:142
1021 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1022 | return err
1023 | }
1024 | //line page.ego:143
1025 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1026 | return err
1027 | }
1028 | //line page.ego:144
1029 | for i := 0; i < len(values); i++ {
1030 | //line page.ego:145
1031 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1032 | return err
1033 | }
1034 | //line page.ego:145
1035 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1036 | return err
1037 | }
1038 | //line page.ego:146
1039 | if _, err := fmt.Fprintf(w, "| "); err != nil {
1040 | return err
1041 | }
1042 | //line page.ego:146
1043 | if _, err := fmt.Fprintf(w, "%v", mins[i]); err != nil {
1044 | return err
1045 | }
1046 | //line page.ego:146
1047 | if _, err := fmt.Fprintf(w, " - "); err != nil {
1048 | return err
1049 | }
1050 | //line page.ego:146
1051 | if _, err := fmt.Fprintf(w, "%v", maxs[i]); err != nil {
1052 | return err
1053 | }
1054 | //line page.ego:146
1055 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1056 | return err
1057 | }
1058 | //line page.ego:147
1059 | if _, err := fmt.Fprintf(w, " | "); err != nil {
1060 | return err
1061 | }
1062 | //line page.ego:147
1063 | if _, err := fmt.Fprintf(w, "%v", values[i]); err != nil {
1064 | return err
1065 | }
1066 | //line page.ego:147
1067 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1068 | return err
1069 | }
1070 | //line page.ego:148
1071 | if _, err := fmt.Fprintf(w, " | "); err != nil {
1072 | return err
1073 | }
1074 | //line page.ego:148
1075 | if _, err := fmt.Fprintf(w, "%v", strings.Repeat("█", int((float64(values[i])/float64(vmax))*float64(maxlen)))); err != nil {
1076 | return err
1077 | }
1078 | //line page.ego:148
1079 | if _, err := fmt.Fprintf(w, " | \n "); err != nil {
1080 | return err
1081 | }
1082 | //line page.ego:149
1083 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
1084 | return err
1085 | }
1086 | //line page.ego:150
1087 | }
1088 | //line page.ego:151
1089 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1090 | return err
1091 | }
1092 | //line page.ego:151
1093 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1094 | return err
1095 | }
1096 | //line page.ego:152
1097 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
1098 | return err
1099 | }
1100 | //line page.ego:153
1101 | } else {
1102 | //line page.ego:154
1103 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1104 | return err
1105 | }
1106 | //line page.ego:155
1107 | u, q := r.URL, r.URL.Query()
1108 | q.Set("usage", "true")
1109 | u.RawQuery = q.Encode()
1110 |
1111 | //line page.ego:160
1112 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
1113 | return err
1114 | }
1115 | //line page.ego:161
1116 | if _, err := fmt.Fprintf(w, ""); err != nil {
1117 | return err
1118 | }
1119 | //line page.ego:161
1120 | if _, err := fmt.Fprintf(w, "Show Page Usage"); err != nil {
1129 | return err
1130 | }
1131 | //line page.ego:161
1132 | if _, err := fmt.Fprintf(w, ""); err != nil {
1133 | return err
1134 | }
1135 | //line page.ego:161
1136 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
1137 | return err
1138 | }
1139 | //line page.ego:162
1140 | }
1141 | //line page.ego:163
1142 | if _, err := fmt.Fprintf(w, "\n\n "); err != nil {
1143 | return err
1144 | }
1145 | //line page.ego:164
1146 | if _, err := fmt.Fprintf(w, "
"); err != nil {
1147 | return err
1148 | }
1149 | //line page.ego:164
1150 | if _, err := fmt.Fprintf(w, "
\n "); err != nil {
1151 | return err
1152 | }
1153 | //line page.ego:165
1154 | if _, err := fmt.Fprintf(w, "\n "); err != nil {
1171 | return err
1172 | }
1173 | //line page.ego:169
1174 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
1175 | return err
1176 | }
1177 | //line page.ego:170
1178 | if _, err := fmt.Fprintf(w, "\n"); err != nil {
1179 | return err
1180 | }
1181 | return nil
1182 | }
1183 |
--------------------------------------------------------------------------------