master
go 156 lines 5.01 KB
Raw
1 package badgerds
2
3 import (
4 "fmt"
5 "os"
6 "path/filepath"
7
8 logging "github.com/ipfs/go-log/v2"
9 "github.com/ipfs/kubo/plugin"
10 "github.com/ipfs/kubo/repo"
11 "github.com/ipfs/kubo/repo/fsrepo"
12
13 humanize "github.com/dustin/go-humanize"
14 badgerds "github.com/ipfs/go-ds-badger"
15 )
16
17 var log = logging.Logger("plugin/badgerds")
18
19 // Plugins is exported list of plugins that will be loaded.
20 var Plugins = []plugin.Plugin{
21 &badgerdsPlugin{},
22 }
23
24 type badgerdsPlugin struct{}
25
26 var _ plugin.PluginDatastore = (*badgerdsPlugin)(nil)
27
28 func (*badgerdsPlugin) Name() string {
29 return "ds-badgerds"
30 }
31
32 func (*badgerdsPlugin) Version() string {
33 return "0.1.0"
34 }
35
36 func (*badgerdsPlugin) Init(_ *plugin.Environment) error {
37 return nil
38 }
39
40 func (*badgerdsPlugin) DatastoreTypeName() string {
41 return "badgerds"
42 }
43
44 type datastoreConfig struct {
45 path string
46 syncWrites bool
47 truncate bool
48
49 vlogFileSize int64
50 }
51
52 // BadgerdsDatastoreConfig returns a configuration stub for a badger datastore
53 // from the given parameters.
54 func (*badgerdsPlugin) DatastoreConfigParser() fsrepo.ConfigFromMap {
55 return func(params map[string]any) (fsrepo.DatastoreConfig, error) {
56 var c datastoreConfig
57 var ok bool
58
59 c.path, ok = params["path"].(string)
60 if !ok {
61 return nil, fmt.Errorf("'path' field is missing or not string")
62 }
63
64 sw, ok := params["syncWrites"]
65 if !ok {
66 c.syncWrites = false
67 } else {
68 if swb, ok := sw.(bool); ok {
69 c.syncWrites = swb
70 } else {
71 return nil, fmt.Errorf("'syncWrites' field was not a boolean")
72 }
73 }
74
75 truncate, ok := params["truncate"]
76 if !ok {
77 c.truncate = true
78 } else {
79 if truncate, ok := truncate.(bool); ok {
80 c.truncate = truncate
81 } else {
82 return nil, fmt.Errorf("'truncate' field was not a boolean")
83 }
84 }
85
86 vls, ok := params["vlogFileSize"]
87 if !ok {
88 // default to 1GiB
89 c.vlogFileSize = badgerds.DefaultOptions.ValueLogFileSize
90 } else {
91 if vlogSize, ok := vls.(string); ok {
92 s, err := humanize.ParseBytes(vlogSize)
93 if err != nil {
94 return nil, err
95 }
96 c.vlogFileSize = int64(s)
97 } else {
98 return nil, fmt.Errorf("'vlogFileSize' field was not a string")
99 }
100 }
101
102 return &c, nil
103 }
104 }
105
106 func (c *datastoreConfig) DiskSpec() fsrepo.DiskSpec {
107 return map[string]any{
108 "type": "badgerds",
109 "path": c.path,
110 }
111 }
112
113 func (c *datastoreConfig) Create(path string) (repo.Datastore, error) {
114 log.Error("badger v1 datastore is deprecated and will be removed later in 2026, migrate to flatfs or experimental pebbleds: https://github.com/ipfs/kubo/issues/11186")
115 fmt.Fprintf(os.Stderr, `
116 ╔════════════════════════════════════════════════════════════════════════════╗
117 ║ ║
118 ║ ERROR: BADGER v1 DATASTORE IS DEPRECATED ║
119 ║ ║
120 ║ This datastore is based on badger 1.x which has not been maintained ║
121 ║ by its upstream maintainers for years and has known bugs (startup ║
122 ║ timeouts, shutdown hangs, file descriptor exhaustion, and more). ║
123 ║ ║
124 ║ Badger v1 support will be REMOVED later in 2026. ║
125 ║ ║
126 ║ To migrate: ║
127 ║ 1. Create a new IPFS_PATH with flatfs (or experimental pebbleds ║
128 ║ if flatfs does not serve your use case): ║
129 ║ export IPFS_PATH=/path/to/new/repo ║
130 ║ ipfs init --profile=flatfs ║
131 ║ 2. Move pinned data via ipfs dag export/import ║
132 ║ or ipfs pin ls -t recursive|add ║
133 ║ 3. Decommission the old badger-based node ║
134 ║ ║
135 ║ See https://github.com/ipfs/kubo/blob/master/docs/datastores.md ║
136 ║ https://github.com/ipfs/kubo/issues/11186 ║
137 ║ ║
138 ╚════════════════════════════════════════════════════════════════════════════╝
139 `)
140 p := c.path
141 if !filepath.IsAbs(p) {
142 p = filepath.Join(path, p)
143 }
144
145 err := os.MkdirAll(p, 0o755)
146 if err != nil {
147 return nil, err
148 }
149
150 defopts := badgerds.DefaultOptions
151 defopts.SyncWrites = c.syncWrites
152 defopts.Truncate = c.truncate
153 defopts.ValueLogFileSize = c.vlogFileSize
154
155 return badgerds.NewDatastore(p, &defopts)
156 }