github.com/klaytn/klaytn@v1.12.1/storage/database/interface.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from ethdb/interface.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package database
    22  
    23  import "strings"
    24  
    25  // Code using batches should try to add this much data to the batch.
    26  // The value was determined empirically.
    27  
    28  type DBType string
    29  
    30  const (
    31  	LevelDB   DBType = "LevelDB"
    32  	RocksDB          = "RocksDB"
    33  	BadgerDB         = "BadgerDB"
    34  	MemoryDB         = "MemoryDB"
    35  	DynamoDB         = "DynamoDBS3"
    36  	ShardedDB        = "ShardedDB"
    37  )
    38  
    39  // ToValid converts DBType to a valid one.
    40  // If it is unable to convert, "" is returned.
    41  func (db DBType) ToValid() DBType {
    42  	validDBType := []DBType{LevelDB, RocksDB, BadgerDB, MemoryDB, DynamoDB}
    43  
    44  	for _, vdb := range validDBType {
    45  		if strings.ToLower(string(vdb)) == strings.ToLower(string(db)) {
    46  			return vdb
    47  		}
    48  	}
    49  
    50  	return ""
    51  }
    52  
    53  // selfShardable returns if the db is able to shard by itself or not
    54  func (db DBType) selfShardable() bool {
    55  	switch db {
    56  	case DynamoDB:
    57  		return true
    58  	}
    59  	return false
    60  }
    61  
    62  // KeyValueWriter wraps the Put method of a backing data store.
    63  type KeyValueWriter interface {
    64  	// Put inserts the given value into the key-value data store.
    65  	Put(key []byte, value []byte) error
    66  
    67  	// Delete removes the key from the key-value data store.
    68  	Delete(key []byte) error
    69  }
    70  
    71  // KeyValueStater wraps the Stat method of a backing data store.
    72  type KeyValueStater interface {
    73  	// Stat returns a particular internal stat of the database.
    74  	Stat(property string) (string, error)
    75  }
    76  
    77  // Compacter wraps the Compact method of a backing data store.
    78  type Compacter interface {
    79  	// Compact flattens the underlying data store for the given key range. In essence,
    80  	// deleted and overwritten versions are discarded, and the data is rearranged to
    81  	// reduce the cost of operations needed to access them.
    82  	//
    83  	// A nil start is treated as a key before all keys in the data store; a nil limit
    84  	// is treated as a key after all keys in the data store. If both is nil then it
    85  	// will compact entire data store.
    86  	Compact(start []byte, limit []byte) error
    87  }
    88  
    89  // Database wraps all database operations. All methods are safe for concurrent use.
    90  type Database interface {
    91  	KeyValueWriter
    92  	KeyValueStater
    93  	Compacter
    94  
    95  	Get(key []byte) ([]byte, error)
    96  	Has(key []byte) (bool, error)
    97  	Close()
    98  	NewBatch() Batch
    99  	Type() DBType
   100  	Meter(prefix string)
   101  	Iteratee
   102  
   103  	TryCatchUpWithPrimary() error
   104  }
   105  
   106  func WriteBatches(batches ...Batch) (int, error) {
   107  	bytes := 0
   108  	for _, batch := range batches {
   109  		if batch.ValueSize() > 0 {
   110  			bytes += batch.ValueSize()
   111  			if err := batch.Write(); err != nil {
   112  				return 0, err
   113  			}
   114  			batch.Reset()
   115  		}
   116  	}
   117  	return bytes, nil
   118  }
   119  
   120  func WriteBatchesParallel(batches ...Batch) (int, error) {
   121  	type result struct {
   122  		bytes int
   123  		err   error
   124  	}
   125  
   126  	resultCh := make(chan result, len(batches))
   127  	for _, batch := range batches {
   128  		go func(batch Batch) {
   129  			bytes := batch.ValueSize()
   130  			err := batch.Write()
   131  			if err != nil {
   132  				batch.Reset()
   133  			}
   134  			resultCh <- result{bytes, err}
   135  		}(batch)
   136  	}
   137  
   138  	var bytes int
   139  	for range batches {
   140  		rst := <-resultCh
   141  		if rst.err != nil {
   142  			return bytes, rst.err
   143  		}
   144  		bytes += rst.bytes
   145  	}
   146  
   147  	return bytes, nil
   148  }
   149  
   150  func WriteBatchesOverThreshold(batches ...Batch) (int, error) {
   151  	bytes := 0
   152  	for _, batch := range batches {
   153  		if batch.ValueSize() >= IdealBatchSize {
   154  			if err := batch.Write(); err != nil {
   155  				return 0, err
   156  			}
   157  			bytes += batch.ValueSize()
   158  			batch.Reset()
   159  		}
   160  	}
   161  	return bytes, nil
   162  }