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  }