github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/search/bleve_leveldb_store.go (about) 1 // Copyright 2019 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package search 6 7 import ( 8 "github.com/blevesearch/bleve/index/store" 9 "github.com/keybase/client/go/kbfs/libfs" 10 "github.com/pkg/errors" 11 "github.com/syndtr/goleveldb/leveldb" 12 ldberrors "github.com/syndtr/goleveldb/leveldb/errors" 13 "github.com/syndtr/goleveldb/leveldb/iterator" 14 "github.com/syndtr/goleveldb/leveldb/storage" 15 "github.com/syndtr/goleveldb/leveldb/util" 16 billy "gopkg.in/src-d/go-billy.v4" 17 ) 18 19 type bleveLevelDBIterator struct { 20 iter iterator.Iterator 21 } 22 23 var _ store.KVIterator = (*bleveLevelDBIterator)(nil) 24 25 // Seek implements the store.KVIterator interface for bleveLevelDBIterator. 26 func (bldbi *bleveLevelDBIterator) Seek(key []byte) { 27 _ = bldbi.iter.Seek(key) 28 } 29 30 // Next implements the store.KVIterator interface for bleveLevelDBIterator. 31 func (bldbi *bleveLevelDBIterator) Next() { 32 _ = bldbi.iter.Next() 33 } 34 35 // Key implements the store.KVIterator interface for bleveLevelDBIterator. 36 func (bldbi *bleveLevelDBIterator) Key() []byte { 37 return bldbi.iter.Key() 38 } 39 40 // Value implements the store.KVIterator interface for bleveLevelDBIterator. 41 func (bldbi *bleveLevelDBIterator) Value() []byte { 42 return bldbi.iter.Value() 43 } 44 45 // Valid implements the store.KVIterator interface for bleveLevelDBIterator. 46 func (bldbi *bleveLevelDBIterator) Valid() bool { 47 return bldbi.iter.Valid() 48 } 49 50 // Current implements the store.KVIterator interface for bleveLevelDBIterator. 51 func (bldbi *bleveLevelDBIterator) Current() ([]byte, []byte, bool) { 52 return bldbi.Key(), bldbi.Value(), bldbi.Valid() 53 } 54 55 // Close implements the store.KVIterator interface for bleveLevelDBIterator. 56 func (bldbi *bleveLevelDBIterator) Close() error { 57 bldbi.iter.Release() 58 return nil 59 } 60 61 type bleveLevelDBReader struct { 62 snap *leveldb.Snapshot 63 } 64 65 var _ store.KVReader = (*bleveLevelDBReader)(nil) 66 67 // Get implements the store.KVReader interface for bleveLevelDBReader. 68 func (bldbr *bleveLevelDBReader) Get(key []byte) ([]byte, error) { 69 v, err := bldbr.snap.Get(key, nil) 70 if err == ldberrors.ErrNotFound { 71 return nil, nil 72 } 73 return v, err 74 } 75 76 // MultiGet implements the store.KVReader interface for bleveLevelDBReader. 77 func (bldbr *bleveLevelDBReader) MultiGet(keys [][]byte) ( 78 values [][]byte, err error) { 79 return store.MultiGet(bldbr, keys) 80 } 81 82 // PrefixIterator implements the store.KVReader interface for bleveLevelDBReader. 83 func (bldbr *bleveLevelDBReader) PrefixIterator(prefix []byte) store.KVIterator { 84 r := util.BytesPrefix(prefix) 85 i := &bleveLevelDBIterator{ 86 iter: bldbr.snap.NewIterator(r, nil), 87 } 88 i.Next() 89 return i 90 } 91 92 // RangeIterator implements the store.KVReader interface for bleveLevelDBReader. 93 func (bldbr *bleveLevelDBReader) RangeIterator( 94 start, end []byte) store.KVIterator { 95 i := &bleveLevelDBIterator{ 96 iter: bldbr.snap.NewIterator(&util.Range{ 97 Start: start, 98 Limit: end, 99 }, nil), 100 } 101 i.Next() 102 return i 103 } 104 105 // Close implements the store.KVReader interface for bleveLevelDBReader. 106 func (bldbr *bleveLevelDBReader) Close() error { 107 bldbr.snap.Release() 108 return nil 109 } 110 111 type bleveLevelDBBatch struct { 112 b *leveldb.Batch 113 m *store.EmulatedMerge 114 } 115 116 func newbleveLevelDBBatch( 117 totalBytes int, mo store.MergeOperator) *bleveLevelDBBatch { 118 return &bleveLevelDBBatch{ 119 b: leveldb.MakeBatch(totalBytes), 120 m: store.NewEmulatedMerge(mo), 121 } 122 } 123 124 var _ store.KVBatch = (*bleveLevelDBBatch)(nil) 125 126 func (bldbb *bleveLevelDBBatch) Set(key, val []byte) { 127 bldbb.b.Put(key, val) 128 } 129 130 func (bldbb *bleveLevelDBBatch) Delete(key []byte) { 131 bldbb.b.Delete(key) 132 } 133 134 func (bldbb *bleveLevelDBBatch) Merge(key, val []byte) { 135 // Adapted from github.com/blevesearch/bleve/index/store/batch.go. 136 ck := make([]byte, len(key)) 137 copy(ck, key) 138 cv := make([]byte, len(val)) 139 copy(cv, val) 140 bldbb.m.Merge(key, val) 141 } 142 143 func (bldbb *bleveLevelDBBatch) Reset() { 144 bldbb.b.Reset() 145 } 146 147 func (bldbb *bleveLevelDBBatch) Close() error { 148 return nil 149 } 150 151 type bleveLevelDBWriter struct { 152 db *leveldb.DB 153 mo store.MergeOperator 154 } 155 156 var _ store.KVWriter = (*bleveLevelDBWriter)(nil) 157 158 // NewBatch implements the store.KVReader interface for bleveLevelDBWriter. 159 func (bldbw *bleveLevelDBWriter) NewBatch() store.KVBatch { 160 return newbleveLevelDBBatch(0, bldbw.mo) 161 } 162 163 // NewBatchEx implements the store.KVReader interface for bleveLevelDBWriter. 164 func (bldbw *bleveLevelDBWriter) NewBatchEx(opts store.KVBatchOptions) ( 165 []byte, store.KVBatch, error) { 166 return make([]byte, opts.TotalBytes), 167 newbleveLevelDBBatch(opts.TotalBytes, bldbw.mo), nil 168 } 169 170 // ExecuteBatch implements the store.KVReader interface for bleveLevelDBWriter. 171 func (bldbw *bleveLevelDBWriter) ExecuteBatch(batch store.KVBatch) error { 172 b, ok := batch.(*bleveLevelDBBatch) 173 if !ok { 174 return errors.Errorf("Unexpected batch type: %T", batch) 175 } 176 177 // Adapted from github.com/blevesearch/bleve/index/store/boltdb/writer.go. 178 for k, mergeOps := range b.m.Merges { 179 kb := []byte(k) 180 existingVal, err := bldbw.db.Get(kb, nil) 181 if err == ldberrors.ErrNotFound { 182 existingVal = nil 183 } else if err != nil { 184 return err 185 } 186 187 mergedVal, fullMergeOk := bldbw.mo.FullMerge(kb, existingVal, mergeOps) 188 if !fullMergeOk { 189 return errors.Errorf("merge operator returned failure") 190 } 191 b.Set(kb, mergedVal) 192 } 193 194 return bldbw.db.Write(b.b, nil) 195 } 196 197 // Close implements the store.KVReader interface for bleveLevelDBWriter. 198 func (bldbw *bleveLevelDBWriter) Close() error { 199 // Does this need to close outstanding batches allocated by this writer? 200 return nil 201 } 202 203 type bleveLevelDBStore struct { 204 s storage.Storage 205 db *leveldb.DB 206 mo store.MergeOperator 207 } 208 209 var _ store.KVStore = (*bleveLevelDBStore)(nil) 210 211 func newBleveLevelDBStore( 212 bfs billy.Filesystem, readOnly bool, mo store.MergeOperator) ( 213 *bleveLevelDBStore, error) { 214 s, err := libfs.OpenLevelDBStorage(bfs, readOnly) 215 if err != nil { 216 return nil, err 217 } 218 db, err := leveldb.Open(s, nil) 219 if err != nil { 220 return nil, err 221 } 222 return &bleveLevelDBStore{s: s, db: db, mo: mo}, nil 223 } 224 225 // Writer implements the store.KVStore interface for bleveLevelDBStore. 226 func (bldbs *bleveLevelDBStore) Writer() (store.KVWriter, error) { 227 return &bleveLevelDBWriter{db: bldbs.db, mo: bldbs.mo}, nil 228 } 229 230 // Writer implements the store.KVStore interface for bleveLevelDBStore. 231 func (bldbs *bleveLevelDBStore) Reader() (store.KVReader, error) { 232 snap, err := bldbs.db.GetSnapshot() 233 if err != nil { 234 return nil, err 235 } 236 return &bleveLevelDBReader{snap: snap}, nil 237 } 238 239 // close implements the store.KVStore interface for bleveLevelDBStore. 240 func (bldbs *bleveLevelDBStore) Close() error { 241 err := bldbs.db.Close() 242 if err != nil { 243 return err 244 } 245 return bldbs.s.Close() 246 }