github.com/klaytn/klaytn@v1.10.2/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  	BadgerDB         = "BadgerDB"
    33  	MemoryDB         = "MemoryDB"
    34  	DynamoDB         = "DynamoDBS3"
    35  	ShardedDB        = "ShardedDB"
    36  )
    37  
    38  // ToValid converts DBType to a valid one.
    39  // If it is unable to convert, "" is returned.
    40  func (db DBType) ToValid() DBType {
    41  	validDBType := []DBType{LevelDB, BadgerDB, MemoryDB, DynamoDB}
    42  
    43  	for _, vdb := range validDBType {
    44  		if strings.ToLower(string(vdb)) == strings.ToLower(string(db)) {
    45  			return vdb
    46  		}
    47  	}
    48  
    49  	return ""
    50  }
    51  
    52  // selfShardable returns if the db is able to shard by itself or not
    53  func (db DBType) selfShardable() bool {
    54  	switch db {
    55  	case DynamoDB:
    56  		return true
    57  	}
    58  	return false
    59  }
    60  
    61  // KeyValueWriter wraps the Put method of a backing data store.
    62  type KeyValueWriter interface {
    63  	// Put inserts the given value into the key-value data store.
    64  	Put(key []byte, value []byte) error
    65  
    66  	// Delete removes the key from the key-value data store.
    67  	Delete(key []byte) error
    68  }
    69  
    70  // Database wraps all database operations. All methods are safe for concurrent use.
    71  type Database interface {
    72  	KeyValueWriter
    73  	Get(key []byte) ([]byte, error)
    74  	Has(key []byte) (bool, error)
    75  	Close()
    76  	NewBatch() Batch
    77  	Type() DBType
    78  	Meter(prefix string)
    79  	Iteratee
    80  }
    81  
    82  func WriteBatches(batches ...Batch) (int, error) {
    83  	bytes := 0
    84  	for _, batch := range batches {
    85  		if batch.ValueSize() > 0 {
    86  			bytes += batch.ValueSize()
    87  			if err := batch.Write(); err != nil {
    88  				return 0, err
    89  			}
    90  			batch.Reset()
    91  		}
    92  	}
    93  	return bytes, nil
    94  }
    95  
    96  func WriteBatchesParallel(batches ...Batch) (int, error) {
    97  	type result struct {
    98  		bytes int
    99  		err   error
   100  	}
   101  
   102  	resultCh := make(chan result, len(batches))
   103  	for _, batch := range batches {
   104  		go func(batch Batch) {
   105  			bytes := batch.ValueSize()
   106  			err := batch.Write()
   107  			if err != nil {
   108  				batch.Reset()
   109  			}
   110  			resultCh <- result{bytes, err}
   111  		}(batch)
   112  	}
   113  
   114  	var bytes int
   115  	for range batches {
   116  		rst := <-resultCh
   117  		if rst.err != nil {
   118  			return bytes, rst.err
   119  		}
   120  		bytes += rst.bytes
   121  	}
   122  
   123  	return bytes, nil
   124  }
   125  
   126  func WriteBatchesOverThreshold(batches ...Batch) (int, error) {
   127  	bytes := 0
   128  	for _, batch := range batches {
   129  		if batch.ValueSize() >= IdealBatchSize {
   130  			if err := batch.Write(); err != nil {
   131  				return 0, err
   132  			}
   133  			bytes += batch.ValueSize()
   134  			batch.Reset()
   135  		}
   136  	}
   137  	return bytes, nil
   138  }
   139  
   140  func PutAndWriteBatchesOverThreshold(batch Batch, key, val []byte) error {
   141  	if err := batch.Put(key, val); err != nil {
   142  		return err
   143  	}
   144  
   145  	if batch.ValueSize() >= IdealBatchSize {
   146  		if err := batch.Write(); err != nil {
   147  			return err
   148  		}
   149  		batch.Reset()
   150  	}
   151  
   152  	return nil
   153  }