github.com/braveheart12/insolar-09-08-19@v0.8.7/pulsar/storage/pulsestorage_badger.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package pulsarstorage 18 19 import ( 20 "bytes" 21 "encoding/gob" 22 "path/filepath" 23 24 "github.com/dgraph-io/badger" 25 "github.com/insolar/insolar/configuration" 26 "github.com/insolar/insolar/core" 27 "github.com/pkg/errors" 28 ) 29 30 type RecordID string 31 32 const ( 33 LastPulseRecordID RecordID = "lastPulse" 34 PulseRecordID RecordID = "pulse" 35 ) 36 37 // NewDB returns pulsar.storage.db with BadgerDB instance initialized by opts. 38 // Creates database in provided dir or in current directory if dir parameter is empty. 39 func NewStorageBadger(conf configuration.Pulsar, opts *badger.Options) (PulsarStorage, error) { 40 gob.Register(core.Pulse{}) 41 opts = setOptions(opts) 42 dir, err := filepath.Abs(conf.Storage.DataDirectory) 43 if err != nil { 44 return nil, err 45 } 46 47 opts.Dir = dir 48 opts.ValueDir = dir 49 50 bdb, err := badger.Open(*opts) 51 if err != nil { 52 return nil, errors.Wrap(err, "local database open failed") 53 } 54 55 db := &BadgerStorageImpl{ 56 db: bdb, 57 } 58 59 pulse, err := db.GetLastPulse() 60 if pulse.PulseNumber == 0 || err != nil { 61 err = db.SavePulse(core.GenesisPulse) 62 if err != nil { 63 return nil, errors.Wrap(err, "problems with init database") 64 } 65 err = db.SetLastPulse(core.GenesisPulse) 66 if err != nil { 67 return nil, errors.Wrap(err, "problems with init database") 68 } 69 } 70 71 return db, nil 72 } 73 74 func setOptions(o *badger.Options) *badger.Options { 75 newo := &badger.Options{} 76 if o != nil { 77 *newo = *o 78 } else { 79 *newo = badger.DefaultOptions 80 } 81 return newo 82 } 83 84 type BadgerStorageImpl struct { 85 db *badger.DB 86 } 87 88 func (storage *BadgerStorageImpl) GetLastPulse() (*core.Pulse, error) { 89 var pulseNumber core.Pulse 90 91 err := storage.db.View(func(txn *badger.Txn) error { 92 item, err := txn.Get([]byte(LastPulseRecordID)) 93 if err != nil { 94 return err 95 } 96 val, err := item.Value() 97 if err != nil { 98 return err 99 } 100 101 r := bytes.NewBuffer(val) 102 decoder := gob.NewDecoder(r) 103 err = decoder.Decode(&pulseNumber) 104 if err != nil { 105 return err 106 } 107 108 return nil 109 }) 110 return &pulseNumber, err 111 } 112 113 func (storage *BadgerStorageImpl) SetLastPulse(pulse *core.Pulse) error { 114 var buffer bytes.Buffer 115 enc := gob.NewEncoder(&buffer) 116 err := enc.Encode(pulse) 117 if err != nil { 118 return err 119 } 120 return storage.db.Update(func(txn *badger.Txn) error { 121 err := txn.Set([]byte(LastPulseRecordID), buffer.Bytes()) 122 return err 123 }) 124 } 125 126 func (storage *BadgerStorageImpl) SavePulse(pulse *core.Pulse) error { 127 var buffer bytes.Buffer 128 enc := gob.NewEncoder(&buffer) 129 err := enc.Encode(pulse) 130 if err != nil { 131 return err 132 } 133 pulseNumber := pulse.PulseNumber.Bytes() 134 key := []byte(PulseRecordID) 135 key = append(key, pulseNumber...) 136 137 return storage.db.Update(func(txn *badger.Txn) error { 138 err := txn.Set(key, buffer.Bytes()) 139 return err 140 }) 141 } 142 143 func (storage *BadgerStorageImpl) Close() error { 144 return storage.db.Close() 145 }