github.com/ethersphere/bee/v2@v2.2.0/pkg/storage/leveldbstore/store.go (about) 1 // Copyright 2022 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package leveldbstore 6 7 import ( 8 "errors" 9 "fmt" 10 "strings" 11 12 "github.com/ethersphere/bee/v2/pkg/storage" 13 "github.com/syndtr/goleveldb/leveldb" 14 ldbErrors "github.com/syndtr/goleveldb/leveldb/errors" 15 "github.com/syndtr/goleveldb/leveldb/iterator" 16 "github.com/syndtr/goleveldb/leveldb/opt" 17 ldbStorage "github.com/syndtr/goleveldb/leveldb/storage" 18 "github.com/syndtr/goleveldb/leveldb/util" 19 ) 20 21 const separator = "/" 22 23 // key returns the Item identifier for the leveldb storage. 24 func key(item storage.Key) []byte { 25 return []byte(item.Namespace() + separator + item.ID()) 26 } 27 28 // filters is a decorator for a slice of storage.Filters 29 // that helps with its evaluation. 30 type filters []storage.Filter 31 32 // matchAny returns true if any of the filters match the item. 33 func (f filters) matchAny(k string, v []byte) bool { 34 for _, filter := range f { 35 if filter(k, v) { 36 return true 37 } 38 } 39 return false 40 } 41 42 // Storer returns the underlying db store. 43 type Storer interface { 44 DB() *leveldb.DB 45 } 46 47 var ( 48 _ Storer = (*Store)(nil) 49 _ storage.Store = (*Store)(nil) 50 ) 51 52 type Store struct { 53 db *leveldb.DB 54 path string 55 } 56 57 // New returns a new store the backed by leveldb. 58 // If path == "", the leveldb will run with in memory backend storage. 59 func New(path string, opts *opt.Options) (*Store, error) { 60 var ( 61 err error 62 db *leveldb.DB 63 ) 64 65 if path == "" { 66 db, err = leveldb.Open(ldbStorage.NewMemStorage(), opts) 67 } else { 68 db, err = leveldb.OpenFile(path, opts) 69 if ldbErrors.IsCorrupted(err) && !opts.GetReadOnly() { 70 db, err = leveldb.RecoverFile(path, opts) 71 } 72 } 73 74 if err != nil { 75 return nil, err 76 } 77 78 return &Store{ 79 db: db, 80 path: path, 81 }, nil 82 } 83 84 // DB implements the Storer interface. 85 func (s *Store) DB() *leveldb.DB { 86 return s.db 87 } 88 89 // Close implements the storage.Store interface. 90 func (s *Store) Close() (err error) { 91 return s.db.Close() 92 } 93 94 // Get implements the storage.Store interface. 95 func (s *Store) Get(item storage.Item) error { 96 val, err := s.db.Get(key(item), nil) 97 98 if errors.Is(err, leveldb.ErrNotFound) { 99 return storage.ErrNotFound 100 } 101 102 if err != nil { 103 return err 104 } 105 106 if err = item.Unmarshal(val); err != nil { 107 return fmt.Errorf("failed decoding value %w", err) 108 } 109 110 return nil 111 } 112 113 // Has implements the storage.Store interface. 114 func (s *Store) Has(k storage.Key) (bool, error) { 115 return s.db.Has(key(k), nil) 116 } 117 118 // GetSize implements the storage.Store interface. 119 func (s *Store) GetSize(k storage.Key) (int, error) { 120 val, err := s.db.Get(key(k), nil) 121 122 if errors.Is(err, leveldb.ErrNotFound) { 123 return 0, storage.ErrNotFound 124 } 125 126 if err != nil { 127 return 0, err 128 } 129 130 return len(val), nil 131 } 132 133 // Iterate implements the storage.Store interface. 134 func (s *Store) Iterate(q storage.Query, fn storage.IterateFn) error { 135 if err := q.Validate(); err != nil { 136 return fmt.Errorf("failed iteration: %w", err) 137 } 138 139 var retErr error 140 141 var iter iterator.Iterator 142 var prefix string 143 144 defer func() { 145 if iter != nil { 146 iter.Release() 147 } 148 }() 149 150 iterOpts := &opt.ReadOptions{ 151 DontFillCache: true, 152 } 153 154 if q.PrefixAtStart { 155 prefix = q.Factory().Namespace() 156 iter = s.db.NewIterator(util.BytesPrefix([]byte(prefix)), iterOpts) 157 exists := iter.Seek([]byte(prefix + separator + q.Prefix)) 158 if !exists { 159 return nil 160 } 161 _ = iter.Prev() 162 } else { 163 // this is a small hack to make the iteration work with the 164 // old implementation of statestore. this allows us to do a 165 // full iteration without looking at the prefix. 166 if q.Factory().Namespace() != "" { 167 prefix = q.Factory().Namespace() + separator + q.Prefix 168 } 169 iter = s.db.NewIterator(util.BytesPrefix([]byte(prefix)), iterOpts) 170 } 171 172 nextF := iter.Next 173 174 if q.Order == storage.KeyDescendingOrder { 175 nextF = func() bool { 176 nextF = iter.Prev 177 return iter.Last() 178 } 179 } 180 181 firstSkipped := !q.SkipFirst 182 183 for nextF() { 184 keyRaw := iter.Key() 185 nextKey := make([]byte, len(keyRaw)) 186 copy(nextKey, keyRaw) 187 188 valRaw := iter.Value() 189 nextVal := make([]byte, len(valRaw)) 190 copy(nextVal, valRaw) 191 192 key := strings.TrimPrefix(string(nextKey), prefix) 193 194 if filters(q.Filters).matchAny(key, nextVal) { 195 continue 196 } 197 198 if q.SkipFirst && !firstSkipped { 199 firstSkipped = true 200 continue 201 } 202 203 var ( 204 res *storage.Result 205 err error 206 ) 207 208 switch q.ItemProperty { 209 case storage.QueryItemID, storage.QueryItemSize: 210 res = &storage.Result{ID: key, Size: len(nextVal)} 211 case storage.QueryItem: 212 newItem := q.Factory() 213 err = newItem.Unmarshal(nextVal) 214 res = &storage.Result{ID: key, Entry: newItem} 215 } 216 217 if err != nil { 218 retErr = errors.Join(retErr, fmt.Errorf("failed unmarshaling: %w", err)) 219 break 220 } 221 222 if res == nil { 223 retErr = errors.Join(retErr, fmt.Errorf("unknown object attribute type: %v", q.ItemProperty)) 224 break 225 } 226 227 if stop, err := fn(*res); err != nil { 228 retErr = errors.Join(retErr, fmt.Errorf("iterate callback function errored: %w", err)) 229 break 230 } else if stop { 231 break 232 } 233 } 234 235 if err := iter.Error(); err != nil { 236 retErr = errors.Join(retErr, err) 237 } 238 239 return retErr 240 } 241 242 // Count implements the storage.Store interface. 243 func (s *Store) Count(key storage.Key) (int, error) { 244 keys := util.BytesPrefix([]byte(key.Namespace() + separator)) 245 iter := s.db.NewIterator(keys, nil) 246 247 var c int 248 for iter.Next() { 249 c++ 250 } 251 252 iter.Release() 253 254 return c, iter.Error() 255 } 256 257 // Put implements the storage.Store interface. 258 func (s *Store) Put(item storage.Item) error { 259 value, err := item.Marshal() 260 if err != nil { 261 return fmt.Errorf("failed serializing: %w", err) 262 } 263 264 return s.db.Put(key(item), value, nil) 265 } 266 267 // Delete implements the storage.Store interface. 268 func (s *Store) Delete(item storage.Item) error { 269 // this is a small hack to make the deletion of old entries work. As they 270 // don't have a namespace, we need to check for that and use the ID as key without 271 // the separator. 272 var k []byte 273 if item.Namespace() == "" { 274 k = []byte(item.ID()) 275 } else { 276 k = key(item) 277 } 278 279 return s.db.Delete(k, nil) 280 }