github.com/braveheart12/just@v0.8.7/ledger/storage/pulsetrackerdb.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 "bytes" 21 "context" 22 "encoding/hex" 23 "errors" 24 25 "github.com/insolar/insolar/core" 26 "github.com/ugorji/go/codec" 27 ) 28 29 type pulseTracker struct { 30 DB DBContext `inject:""` 31 } 32 33 // NewPulseTracker returns new instance PulseTracker with DB-storage realization 34 func NewPulseTracker() PulseTracker { 35 return new(pulseTracker) 36 } 37 38 // Bytes serializes pulse. 39 func (p *Pulse) Bytes() []byte { 40 var buf bytes.Buffer 41 enc := codec.NewEncoder(&buf, &codec.CborHandle{}) 42 enc.MustEncode(p) 43 return buf.Bytes() 44 } 45 46 func toPulse(raw []byte) (*Pulse, error) { 47 dec := codec.NewDecoder(bytes.NewReader(raw), &codec.CborHandle{}) 48 var rec Pulse 49 err := dec.Decode(&rec) 50 if err != nil { 51 return nil, err 52 } 53 return &rec, nil 54 } 55 56 // GetPulse returns pulse for provided pulse number. 57 func (m *TransactionManager) GetPulse(ctx context.Context, num core.PulseNumber) (*Pulse, error) { 58 buf, err := m.get(ctx, prefixkey(scopeIDPulse, num.Bytes())) 59 if err != nil { 60 return nil, err 61 } 62 63 dec := codec.NewDecoder(bytes.NewReader(buf), &codec.CborHandle{}) 64 var rec Pulse 65 err = dec.Decode(&rec) 66 if err != nil { 67 return nil, err 68 } 69 return &rec, nil 70 } 71 72 // AddPulse saves new pulse data and updates index. 73 func (pt *pulseTracker) AddPulse(ctx context.Context, pulse core.Pulse) error { 74 return pt.DB.Update(ctx, func(tx *TransactionManager) error { 75 var ( 76 previousPulseNumber core.PulseNumber 77 previousSerialNumber int 78 ) 79 80 _, err := tx.get(ctx, prefixkey(scopeIDPulse, pulse.PulseNumber.Bytes())) 81 if err == nil { 82 return ErrOverride 83 } else if err != core.ErrNotFound { 84 return err 85 } 86 87 previousPulse, err := tx.GetLatestPulse(ctx) 88 if err != nil && err != core.ErrNotFound { 89 return err 90 } 91 92 // Set next on previousPulseNumber pulse if it exists. 93 if err == nil { 94 if previousPulse != nil { 95 previousPulseNumber = previousPulse.Pulse.PulseNumber 96 previousSerialNumber = previousPulse.SerialNumber 97 } 98 99 prevPulse, err := tx.GetPulse(ctx, previousPulseNumber) 100 if err != nil { 101 return err 102 } 103 prevPulse.Next = &pulse.PulseNumber 104 err = tx.set(ctx, prefixkey(scopeIDPulse, previousPulseNumber.Bytes()), prevPulse.Bytes()) 105 if err != nil { 106 return err 107 } 108 } 109 110 // Save new pulse. 111 p := Pulse{ 112 Prev: &previousPulseNumber, 113 SerialNumber: previousSerialNumber + 1, 114 Pulse: pulse, 115 } 116 err = tx.set(ctx, prefixkey(scopeIDPulse, pulse.PulseNumber.Bytes()), p.Bytes()) 117 if err != nil { 118 return err 119 } 120 121 return tx.set(ctx, prefixkey(scopeIDSystem, []byte{sysLatestPulse}), p.Bytes()) 122 }) 123 } 124 125 // GetPulse returns pulse for provided pulse number. 126 func (pt *pulseTracker) GetPulse(ctx context.Context, num core.PulseNumber) (*Pulse, error) { 127 var ( 128 pulse *Pulse 129 err error 130 ) 131 err = pt.DB.View(ctx, func(tx *TransactionManager) error { 132 pulse, err = tx.GetPulse(ctx, num) 133 return err 134 }) 135 if err != nil { 136 return nil, err 137 } 138 return pulse, nil 139 } 140 141 // GetPreviousPulse returns pulse for provided pulse number. 142 func (pt *pulseTracker) GetPreviousPulse(ctx context.Context, num core.PulseNumber) (*Pulse, error) { 143 var ( 144 pulse *Pulse 145 err error 146 ) 147 err = pt.DB.View(ctx, func(tx *TransactionManager) error { 148 pulse, err = tx.GetPulse(ctx, num) 149 if err != nil { 150 return err 151 } 152 if pulse.Prev == nil { 153 pulse = nil 154 return nil 155 } 156 pulse, err = tx.GetPulse(ctx, *pulse.Prev) 157 return err 158 }) 159 if err != nil { 160 return nil, err 161 } 162 163 return pulse, nil 164 } 165 166 // GetNthPrevPulse returns Nth previous pulse from some pulse number 167 func (pt *pulseTracker) GetNthPrevPulse(ctx context.Context, n uint, num core.PulseNumber) (*Pulse, error) { 168 pulse, err := pt.GetPulse(ctx, num) 169 if err != nil { 170 return nil, err 171 } 172 173 err = pt.DB.View(ctx, func(tx *TransactionManager) error { 174 for n > 0 { 175 if pulse.Prev == nil { 176 pulse = nil 177 return core.ErrNotFound 178 } 179 pulse, err = tx.GetPulse(ctx, *pulse.Prev) 180 if err != nil { 181 return err 182 } 183 n-- 184 } 185 return nil 186 }) 187 if err != nil { 188 return nil, err 189 } 190 191 return pulse, nil 192 } 193 194 // GetLatestPulse returns the latest pulse 195 func (m *TransactionManager) GetLatestPulse(ctx context.Context) (*Pulse, error) { 196 buf, err := m.get(ctx, prefixkey(scopeIDSystem, []byte{sysLatestPulse})) 197 if err != nil { 198 return nil, err 199 } 200 return toPulse(buf) 201 } 202 203 // Deprecated: use core.PulseStorage.Current() instead (or private getLatestPulse if applicable). 204 func (pt *pulseTracker) GetLatestPulse(ctx context.Context) (*Pulse, error) { 205 return pt.getLatestPulse(ctx) 206 } 207 208 // DeletePulse delete pulse data. 209 func (pt *pulseTracker) DeletePulse(ctx context.Context, num core.PulseNumber) error { 210 return errors.New("DB pulse removal is forbidden") 211 } 212 213 func (pt *pulseTracker) getLatestPulse(ctx context.Context) (*Pulse, error) { 214 tx, err := pt.DB.BeginTransaction(false) 215 if err != nil { 216 return nil, err 217 } 218 defer tx.Discard() 219 220 return tx.GetLatestPulse(ctx) 221 } 222 223 func pulseNumFromKey(from int, key []byte) core.PulseNumber { 224 return core.NewPulseNumber(key[from : from+core.PulseNumberSize]) 225 } 226 227 // Key type for wrapping storage binary key. 228 type Key []byte 229 230 // PulseNumber returns pulse number for provided storage binary key. 231 func (b Key) PulseNumber() core.PulseNumber { 232 // by default expect jetID after: 233 // offset in this case: is 1 + RecordHashSize (jet length) - 1 minus jet prefix 234 from := core.RecordHashSize 235 switch b[0] { 236 case scopeIDPulse: 237 from = 1 238 case scopeIDSystem: 239 // for specific system records is different rules 240 // pulse number could exist or not 241 return 0 242 } 243 return pulseNumFromKey(from, b) 244 } 245 246 // String string hex representation 247 func (b Key) String() string { 248 return hex.EncodeToString(b) 249 }