github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/swarm/state/dbstore.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package state
    18  
    19  import (
    20  	"encoding"
    21  	"encoding/json"
    22  	"errors"
    23  
    24  	"github.com/syndtr/goleveldb/leveldb"
    25  	"github.com/syndtr/goleveldb/leveldb/storage"
    26  )
    27  
    28  // ErrNotFound is returned when no results are returned from the database
    29  var ErrNotFound = errors.New("ErrorNotFound")
    30  
    31  // ErrInvalidArgument is returned when the argument type does not match the expected type
    32  var ErrInvalidArgument = errors.New("ErrorInvalidArgument")
    33  
    34  // Store defines methods required to get, set, delete values for different keys
    35  // and close the underlying resources.
    36  type Store interface {
    37  	Get(key string, i interface{}) (err error)
    38  	Put(key string, i interface{}) (err error)
    39  	Delete(key string) (err error)
    40  	Close() error
    41  }
    42  
    43  // DBStore uses LevelDB to store values.
    44  type DBStore struct {
    45  	db *leveldb.DB
    46  }
    47  
    48  // NewDBStore creates a new instance of DBStore.
    49  func NewDBStore(path string) (s *DBStore, err error) {
    50  	db, err := leveldb.OpenFile(path, nil)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return &DBStore{
    55  		db: db,
    56  	}, nil
    57  }
    58  
    59  // NewInmemoryStore returns a new instance of DBStore. To be used only in tests and simulations.
    60  func NewInmemoryStore() *DBStore {
    61  	db, err := leveldb.Open(storage.NewMemStorage(), nil)
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	return &DBStore{
    66  		db: db,
    67  	}
    68  }
    69  
    70  // Get retrieves a persisted value for a specific key. If there is no results
    71  // ErrNotFound is returned. The provided parameter should be either a byte slice or
    72  // a struct that implements the encoding.BinaryUnmarshaler interface
    73  func (s *DBStore) Get(key string, i interface{}) (err error) {
    74  	has, err := s.db.Has([]byte(key), nil)
    75  	if err != nil || !has {
    76  		return ErrNotFound
    77  	}
    78  
    79  	data, err := s.db.Get([]byte(key), nil)
    80  	if err == leveldb.ErrNotFound {
    81  		return ErrNotFound
    82  	}
    83  
    84  	unmarshaler, ok := i.(encoding.BinaryUnmarshaler)
    85  	if !ok {
    86  		return json.Unmarshal(data, i)
    87  	}
    88  	return unmarshaler.UnmarshalBinary(data)
    89  }
    90  
    91  // Put stores an object that implements Binary for a specific key.
    92  func (s *DBStore) Put(key string, i interface{}) (err error) {
    93  	var bytes []byte
    94  
    95  	marshaler, ok := i.(encoding.BinaryMarshaler)
    96  	if !ok {
    97  		if bytes, err = json.Marshal(i); err != nil {
    98  			return err
    99  		}
   100  	} else {
   101  		if bytes, err = marshaler.MarshalBinary(); err != nil {
   102  			return err
   103  		}
   104  	}
   105  
   106  	return s.db.Put([]byte(key), bytes, nil)
   107  }
   108  
   109  // Delete removes entries stored under a specific key.
   110  func (s *DBStore) Delete(key string) (err error) {
   111  	return s.db.Delete([]byte(key), nil)
   112  }
   113  
   114  // Close releases the resources used by the underlying LevelDB.
   115  func (s *DBStore) Close() error {
   116  	return s.db.Close()
   117  }