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  }