github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/swarm/shed/db.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 shed provides a simple abstraction components to compose
    18  // more complex operations on storage data organized in fields and indexes.
    19  //
    20  // Only type which holds logical information about swarm storage chunks data
    21  // and metadata is IndexItem. This part is not generalized mostly for
    22  // performance reasons.
    23  package shed
    24  
    25  import (
    26  	"github.com/insight-chain/inb-go/metrics"
    27  	"github.com/syndtr/goleveldb/leveldb"
    28  	"github.com/syndtr/goleveldb/leveldb/iterator"
    29  	"github.com/syndtr/goleveldb/leveldb/opt"
    30  )
    31  
    32  // The limit for LevelDB OpenFilesCacheCapacity.
    33  const openFileLimit = 128
    34  
    35  // DB provides abstractions over LevelDB in order to
    36  // implement complex structures using fields and ordered indexes.
    37  // It provides a schema functionality to store fields and indexes
    38  // information about naming and types.
    39  type DB struct {
    40  	ldb *leveldb.DB
    41  }
    42  
    43  // NewDB constructs a new DB and validates the schema
    44  // if it exists in database on the given path.
    45  func NewDB(path string) (db *DB, err error) {
    46  	ldb, err := leveldb.OpenFile(path, &opt.Options{
    47  		OpenFilesCacheCapacity: openFileLimit,
    48  	})
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	db = &DB{
    53  		ldb: ldb,
    54  	}
    55  
    56  	if _, err = db.getSchema(); err != nil {
    57  		if err == leveldb.ErrNotFound {
    58  			// save schema with initialized default fields
    59  			if err = db.putSchema(schema{
    60  				Fields:  make(map[string]fieldSpec),
    61  				Indexes: make(map[byte]indexSpec),
    62  			}); err != nil {
    63  				return nil, err
    64  			}
    65  		} else {
    66  			return nil, err
    67  		}
    68  	}
    69  	return db, nil
    70  }
    71  
    72  // Put wraps LevelDB Put method to increment metrics counter.
    73  func (db *DB) Put(key []byte, value []byte) (err error) {
    74  	err = db.ldb.Put(key, value, nil)
    75  	if err != nil {
    76  		metrics.GetOrRegisterCounter("DB.putFail", nil).Inc(1)
    77  		return err
    78  	}
    79  	metrics.GetOrRegisterCounter("DB.put", nil).Inc(1)
    80  	return nil
    81  }
    82  
    83  // Get wraps LevelDB Get method to increment metrics counter.
    84  func (db *DB) Get(key []byte) (value []byte, err error) {
    85  	value, err = db.ldb.Get(key, nil)
    86  	if err != nil {
    87  		if err == leveldb.ErrNotFound {
    88  			metrics.GetOrRegisterCounter("DB.getNotFound", nil).Inc(1)
    89  		} else {
    90  			metrics.GetOrRegisterCounter("DB.getFail", nil).Inc(1)
    91  		}
    92  		return nil, err
    93  	}
    94  	metrics.GetOrRegisterCounter("DB.get", nil).Inc(1)
    95  	return value, nil
    96  }
    97  
    98  // Delete wraps LevelDB Delete method to increment metrics counter.
    99  func (db *DB) Delete(key []byte) (err error) {
   100  	err = db.ldb.Delete(key, nil)
   101  	if err != nil {
   102  		metrics.GetOrRegisterCounter("DB.deleteFail", nil).Inc(1)
   103  		return err
   104  	}
   105  	metrics.GetOrRegisterCounter("DB.delete", nil).Inc(1)
   106  	return nil
   107  }
   108  
   109  // NewIterator wraps LevelDB NewIterator method to increment metrics counter.
   110  func (db *DB) NewIterator() iterator.Iterator {
   111  	metrics.GetOrRegisterCounter("DB.newiterator", nil).Inc(1)
   112  
   113  	return db.ldb.NewIterator(nil, nil)
   114  }
   115  
   116  // WriteBatch wraps LevelDB Write method to increment metrics counter.
   117  func (db *DB) WriteBatch(batch *leveldb.Batch) (err error) {
   118  	err = db.ldb.Write(batch, nil)
   119  	if err != nil {
   120  		metrics.GetOrRegisterCounter("DB.writebatchFail", nil).Inc(1)
   121  		return err
   122  	}
   123  	metrics.GetOrRegisterCounter("DB.writebatch", nil).Inc(1)
   124  	return nil
   125  }
   126  
   127  // Close closes LevelDB database.
   128  func (db *DB) Close() (err error) {
   129  	return db.ldb.Close()
   130  }