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  }