Line data Source code
1 : // Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
2 : // of this source code is governed by a BSD-style license that can be found in
3 : // the LICENSE file.
4 :
5 : package tool
6 :
7 : import (
8 : "github.com/cockroachdb/pebble"
9 : "github.com/cockroachdb/pebble/bloom"
10 : "github.com/cockroachdb/pebble/internal/base"
11 : "github.com/cockroachdb/pebble/objstorage/remote"
12 : "github.com/cockroachdb/pebble/sstable"
13 : "github.com/cockroachdb/pebble/vfs"
14 : "github.com/spf13/cobra"
15 : )
16 :
17 : // Comparer exports the base.Comparer type.
18 : type Comparer = base.Comparer
19 :
20 : // FilterPolicy exports the base.FilterPolicy type.
21 : type FilterPolicy = base.FilterPolicy
22 :
23 : // Merger exports the base.Merger type.
24 : type Merger = base.Merger
25 :
26 : // T is the container for all of the introspection tools.
27 : type T struct {
28 : Commands []*cobra.Command
29 : db *dbT
30 : find *findT
31 : lsm *lsmT
32 : manifest *manifestT
33 : remotecat *remoteCatalogT
34 : sstable *sstableT
35 : wal *walT
36 : opts pebble.Options
37 : comparers sstable.Comparers
38 : mergers sstable.Mergers
39 : defaultComparer string
40 : openErrEnhancer func(error) error
41 : openOptions []OpenOption
42 : exciseSpanFn DBExciseSpanFn
43 : }
44 :
45 : // A Option configures the Pebble introspection tool.
46 : type Option func(*T)
47 :
48 : // Comparers may be passed to New to register comparers for use by
49 : // the introspesction tools.
50 1 : func Comparers(cmps ...*Comparer) Option {
51 1 : return func(t *T) {
52 1 : for _, c := range cmps {
53 1 : t.comparers[c.Name] = c
54 1 : }
55 : }
56 : }
57 :
58 : // DefaultComparer registers a comparer for use by the introspection tools and
59 : // sets it as the default.
60 1 : func DefaultComparer(c *Comparer) Option {
61 1 : return func(t *T) {
62 1 : t.comparers[c.Name] = c
63 1 : t.defaultComparer = c.Name
64 1 : }
65 : }
66 :
67 : // Mergers may be passed to New to register mergers for use by the
68 : // introspection tools.
69 1 : func Mergers(mergers ...*Merger) Option {
70 1 : return func(t *T) {
71 1 : for _, m := range mergers {
72 1 : t.mergers[m.Name] = m
73 1 : }
74 : }
75 : }
76 :
77 : // Filters may be passed to New to register filter policies for use by the
78 : // introspection tools.
79 1 : func Filters(filters ...FilterPolicy) Option {
80 1 : return func(t *T) {
81 1 : for _, f := range filters {
82 1 : t.opts.Filters[f.Name()] = f
83 1 : }
84 : }
85 : }
86 :
87 : // OpenOptions may be passed to New to provide a set of OpenOptions that should
88 : // be invoked to configure the *pebble.Options before opening a database.
89 0 : func OpenOptions(openOptions ...OpenOption) Option {
90 0 : return func(t *T) {
91 0 : t.openOptions = append(t.openOptions, openOptions...)
92 0 : }
93 : }
94 :
95 : // FS sets the filesystem implementation to use by the introspection tools.
96 1 : func FS(fs vfs.FS) Option {
97 1 : return func(t *T) {
98 1 : t.opts.FS = fs
99 1 : }
100 : }
101 :
102 : // OpenErrEnhancer sets a function that enhances an error encountered when the
103 : // tool opens a database; used to provide the user additional context, for
104 : // example that a corruption error might be caused by encryption at rest not
105 : // being configured properly.
106 1 : func OpenErrEnhancer(fn func(error) error) Option {
107 1 : return func(t *T) {
108 1 : t.openErrEnhancer = fn
109 1 : }
110 : }
111 :
112 : // DBExciseSpanFn is a function used to obtain the excise span for the `db
113 : // excise` command. This allows a higher-level wrapper to add its own way of
114 : // specifying the span. Returns an invalid KeyRange if none was specified (in
115 : // which case the default --start/end flags are used).
116 : type DBExciseSpanFn func() (pebble.KeyRange, error)
117 :
118 : // WithDBExciseSpanFn specifies a function that returns the excise span for the
119 : // `db excise` command.
120 0 : func WithDBExciseSpanFn(fn DBExciseSpanFn) Option {
121 0 : return func(t *T) {
122 0 : t.exciseSpanFn = fn
123 0 : }
124 : }
125 :
126 : // New creates a new introspection tool.
127 1 : func New(opts ...Option) *T {
128 1 : t := &T{
129 1 : opts: pebble.Options{
130 1 : Filters: make(map[string]FilterPolicy),
131 1 : FS: vfs.Default,
132 1 : ReadOnly: true,
133 1 : },
134 1 : comparers: make(sstable.Comparers),
135 1 : mergers: make(sstable.Mergers),
136 1 : defaultComparer: base.DefaultComparer.Name,
137 1 : }
138 1 :
139 1 : opts = append(opts,
140 1 : Comparers(base.DefaultComparer),
141 1 : Filters(bloom.FilterPolicy(10)),
142 1 : Mergers(base.DefaultMerger))
143 1 :
144 1 : for _, opt := range opts {
145 1 : opt(t)
146 1 : }
147 :
148 1 : t.db = newDB(&t.opts, t.comparers, t.mergers, t.openErrEnhancer, t.openOptions, t.exciseSpanFn)
149 1 : t.find = newFind(&t.opts, t.comparers, t.defaultComparer, t.mergers)
150 1 : t.lsm = newLSM(&t.opts, t.comparers)
151 1 : t.manifest = newManifest(&t.opts, t.comparers)
152 1 : t.remotecat = newRemoteCatalog(&t.opts)
153 1 : t.sstable = newSSTable(&t.opts, t.comparers, t.mergers)
154 1 : t.wal = newWAL(&t.opts, t.comparers, t.defaultComparer)
155 1 : t.Commands = []*cobra.Command{
156 1 : t.db.Root,
157 1 : t.find.Root,
158 1 : t.lsm.Root,
159 1 : t.manifest.Root,
160 1 : t.remotecat.Root,
161 1 : t.sstable.Root,
162 1 : t.wal.Root,
163 1 : }
164 1 : return t
165 : }
166 :
167 : // ConfigureSharedStorage updates the shared storage options.
168 : func (t *T) ConfigureSharedStorage(
169 : s remote.StorageFactory,
170 : createOnShared remote.CreateOnSharedStrategy,
171 : createOnSharedLocator remote.Locator,
172 0 : ) {
173 0 : t.opts.Experimental.RemoteStorage = s
174 0 : t.opts.Experimental.CreateOnShared = createOnShared
175 0 : t.opts.Experimental.CreateOnSharedLocator = createOnSharedLocator
176 0 : }
|