github.com/braveheart12/insolar-09-08-19@v0.8.7/ledger/storage/dropstorage.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 storage 18 19 import ( 20 "context" 21 "sync" 22 23 "github.com/dgraph-io/badger" 24 "github.com/insolar/insolar/core" 25 "github.com/insolar/insolar/ledger/storage/jet" 26 "github.com/pkg/errors" 27 ) 28 29 // DropStorage jet-drops 30 //go:generate minimock -i github.com/insolar/insolar/ledger/storage.DropStorage -o ./ -s _mock.go 31 type DropStorage interface { 32 CreateDrop(ctx context.Context, jetID core.RecordID, pulse core.PulseNumber, prevHash []byte) ( 33 *jet.JetDrop, 34 [][]byte, 35 uint64, 36 error, 37 ) 38 SetDrop(ctx context.Context, jetID core.RecordID, drop *jet.JetDrop) error 39 GetDrop(ctx context.Context, jetID core.RecordID, pulse core.PulseNumber) (*jet.JetDrop, error) 40 41 AddDropSize(ctx context.Context, dropSize *jet.DropSize) error 42 SetDropSizeHistory(ctx context.Context, jetID core.RecordID, dropSizeHistory jet.DropSizeHistory) error 43 GetDropSizeHistory(ctx context.Context, jetID core.RecordID) (jet.DropSizeHistory, error) 44 45 GetJetSizesHistoryDepth() int 46 } 47 48 type dropStorage struct { 49 DB DBContext `inject:""` 50 PlatformCryptographyScheme core.PlatformCryptographyScheme `inject:""` 51 52 addBlockSizeLock sync.RWMutex 53 jetSizesHistoryDepth int 54 } 55 56 func NewDropStorage(jetSizesHistoryDepth int) DropStorage { 57 return &dropStorage{jetSizesHistoryDepth: jetSizesHistoryDepth} 58 } 59 60 // CreateDrop creates and stores jet drop for given pulse number. 61 // 62 // On success returns saved drop object, slot records, drop size. 63 func (ds *dropStorage) CreateDrop(ctx context.Context, jetID core.RecordID, pulse core.PulseNumber, prevHash []byte) ( 64 *jet.JetDrop, 65 [][]byte, 66 uint64, 67 error, 68 ) { 69 var err error 70 ds.DB.waitingFlight() 71 72 hw := ds.PlatformCryptographyScheme.ReferenceHasher() 73 _, err = hw.Write(prevHash) 74 if err != nil { 75 return nil, nil, 0, err 76 } 77 78 var messages [][]byte 79 _, jetPrefix := jet.Jet(jetID) 80 // messagesPrefix := prefixkey(scopeIDMessage, jetPrefix, pulse.Bytes()) 81 82 // err = db.db.View(func(txn *badger.Txn) error { 83 // it := txn.NewIterator(badger.DefaultIteratorOptions) 84 // defer it.Close() 85 // 86 // for it.Seek(messagesPrefix); it.ValidForPrefix(messagesPrefix); it.Next() { 87 // val, err := it.Item().ValueCopy(nil) 88 // if err != nil { 89 // return err 90 // } 91 // messages = append(messages, val) 92 // } 93 // return nil 94 // }) 95 // if err != nil { 96 // return nil, nil, 0, err 97 // } 98 99 var dropSize uint64 100 recordPrefix := prefixkey(scopeIDRecord, jetPrefix, pulse.Bytes()) 101 102 err = ds.DB.GetBadgerDB().View(func(txn *badger.Txn) error { 103 it := txn.NewIterator(badger.DefaultIteratorOptions) 104 defer it.Close() 105 106 for it.Seek(recordPrefix); it.ValidForPrefix(recordPrefix); it.Next() { 107 val, err := it.Item().ValueCopy(nil) 108 if err != nil { 109 return err 110 } 111 _, err = hw.Write(val) 112 if err != nil { 113 return err 114 } 115 dropSize += uint64(len(val)) 116 } 117 return nil 118 }) 119 if err != nil { 120 return nil, nil, 0, err 121 } 122 123 drop := jet.JetDrop{ 124 Pulse: pulse, 125 PrevHash: prevHash, 126 Hash: hw.Sum(nil), 127 } 128 return &drop, messages, dropSize, nil 129 } 130 131 // SetDrop saves provided JetDrop in db. 132 func (ds *dropStorage) SetDrop(ctx context.Context, jetID core.RecordID, drop *jet.JetDrop) error { 133 _, prefix := jet.Jet(jetID) 134 k := prefixkey(scopeIDJetDrop, prefix, drop.Pulse.Bytes()) 135 _, err := ds.DB.get(ctx, k) 136 if err == nil { 137 return ErrOverride 138 } 139 140 encoded, err := jet.Encode(drop) 141 if err != nil { 142 return err 143 } 144 return ds.DB.set(ctx, k, encoded) 145 } 146 147 // GetDrop returns jet drop for a given pulse number and jet id. 148 func (ds *dropStorage) GetDrop(ctx context.Context, jetID core.RecordID, pulse core.PulseNumber) (*jet.JetDrop, error) { 149 _, prefix := jet.Jet(jetID) 150 k := prefixkey(scopeIDJetDrop, prefix, pulse.Bytes()) 151 152 // buf, err := db.get(ctx, k) 153 buf, err := ds.DB.get(ctx, k) 154 if err != nil { 155 return nil, err 156 } 157 drop, err := jet.Decode(buf) 158 if err != nil { 159 return nil, err 160 } 161 return drop, nil 162 } 163 164 // AddDropSize adds Jet drop size stats (required for split decision). 165 func (ds *dropStorage) AddDropSize(ctx context.Context, dropSize *jet.DropSize) error { 166 ds.addBlockSizeLock.Lock() 167 defer ds.addBlockSizeLock.Unlock() 168 169 k := dropSizesPrefixKey(dropSize.JetID) 170 buff, err := ds.DB.get(ctx, k) 171 if err != nil && err != core.ErrNotFound { 172 return errors.Wrapf(err, "[ AddDropSize ] Can't get object: %s", string(k)) 173 } 174 175 var dropSizes = jet.DropSizeHistory{} 176 if err != core.ErrNotFound { 177 dropSizes, err = jet.DeserializeJetDropSizeHistory(ctx, buff) 178 if err != nil { 179 return errors.Wrapf(err, "[ AddDropSize ] Can't decode dropSizes") 180 } 181 182 if len([]jet.DropSize(dropSizes)) >= ds.jetSizesHistoryDepth { 183 dropSizes = dropSizes[1:] 184 } 185 } 186 187 dropSizes = append(dropSizes, *dropSize) 188 189 return ds.DB.set(ctx, k, dropSizes.Bytes()) 190 } 191 192 // SetDropSizeHistory saves drop sizes history. 193 func (ds *dropStorage) SetDropSizeHistory(ctx context.Context, jetID core.RecordID, dropSizeHistory jet.DropSizeHistory) error { 194 ds.addBlockSizeLock.Lock() 195 defer ds.addBlockSizeLock.Unlock() 196 197 k := dropSizesPrefixKey(jetID) 198 err := ds.DB.set(ctx, k, dropSizeHistory.Bytes()) 199 return errors.Wrap(err, "[ ResetDropSizeHistory ] Can't db.set") 200 } 201 202 // GetDropSizeHistory returns last drops sizes. 203 func (ds *dropStorage) GetDropSizeHistory(ctx context.Context, jetID core.RecordID) (jet.DropSizeHistory, error) { 204 ds.addBlockSizeLock.RLock() 205 defer ds.addBlockSizeLock.RUnlock() 206 207 k := dropSizesPrefixKey(jetID) 208 buff, err := ds.DB.get(ctx, k) 209 if err != nil && err != core.ErrNotFound { 210 return nil, errors.Wrap(err, "[ GetDropSizeHistory ] Can't db.set") 211 } 212 213 if err == core.ErrNotFound { 214 return jet.DropSizeHistory{}, nil 215 } 216 217 dropSizes, err := jet.DeserializeJetDropSizeHistory(ctx, buff) 218 if err != nil { 219 return nil, errors.Wrapf(err, "[ GetDropSizeHistory ] Can't decode dropSizes") 220 } 221 222 return dropSizes, nil 223 } 224 225 // GetJetSizesHistoryDepth returns max amount of drop sizes 226 func (ds *dropStorage) GetJetSizesHistoryDepth() int { 227 return ds.jetSizesHistoryDepth 228 } 229 230 func dropSizesPrefixKey(jetID core.RecordID) []byte { 231 return prefixkey(scopeIDSystem, []byte{sysDropSizeHistory}, jetID.Bytes()) 232 }