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 }