github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/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  )
    26  
    27  // ErrNotFound is returned when no results are returned from the database
    28  var ErrNotFound = errors.New("ErrorNotFound")
    29  
    30  // ErrInvalidArgument is returned when the argument type does not match the expected type
    31  var ErrInvalidArgument = errors.New("ErrorInvalidArgument")
    32  
    33  // DBStore uses LevelDB to store values.
    34  type DBStore struct {
    35  	db *leveldb.DB
    36  }
    37  
    38  // NewDBStore creates a new instance of DBStore.
    39  func NewDBStore(path string) (s *DBStore, err error) {
    40  	db, err := leveldb.OpenFile(path, nil)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	return &DBStore{
    45  		db: db,
    46  	}, nil
    47  }
    48  
    49  // Get retrieves a persisted value for a specific key. If there is no results
    50  // ErrNotFound is returned. The provided parameter should be either a byte slice or
    51  // a struct that implements the encoding.BinaryUnmarshaler interface
    52  func (s *DBStore) Get(key string, i interface{}) (err error) {
    53  	has, err := s.db.Has([]byte(key), nil)
    54  	if err != nil || !has {
    55  		return ErrNotFound
    56  	}
    57  
    58  	data, err := s.db.Get([]byte(key), nil)
    59  	if err == leveldb.ErrNotFound {
    60  		return ErrNotFound
    61  	}
    62  
    63  	unmarshaler, ok := i.(encoding.BinaryUnmarshaler)
    64  	if !ok {
    65  		return json.Unmarshal(data, i)
    66  	}
    67  	return unmarshaler.UnmarshalBinary(data)
    68  }
    69  
    70  // Put stores an object that implements Binary for a specific key.
    71  func (s *DBStore) Put(key string, i interface{}) (err error) {
    72  	bytes := []byte{}
    73  
    74  	marshaler, ok := i.(encoding.BinaryMarshaler)
    75  	if !ok {
    76  		if bytes, err = json.Marshal(i); err != nil {
    77  			return err
    78  		}
    79  	} else {
    80  		if bytes, err = marshaler.MarshalBinary(); err != nil {
    81  			return err
    82  		}
    83  	}
    84  
    85  	return s.db.Put([]byte(key), bytes, nil)
    86  }
    87  
    88  // Delete removes entries stored under a specific key.
    89  func (s *DBStore) Delete(key string) (err error) {
    90  	return s.db.Delete([]byte(key), nil)
    91  }
    92  
    93  // Close releases the resources used by the underlying LevelDB.
    94  func (s *DBStore) Close() error {
    95  	return s.db.Close()
    96  }