github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/cmd/dummytx/db/db.go (about) 1 package db 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "sync" 8 9 "github.com/bigzoro/my_simplechain/common" 10 "github.com/bigzoro/my_simplechain/common/hexutil" 11 12 "github.com/syndtr/goleveldb/leveldb" 13 "github.com/syndtr/goleveldb/leveldb/errors" 14 "github.com/syndtr/goleveldb/leveldb/filter" 15 "github.com/syndtr/goleveldb/leveldb/iterator" 16 "github.com/syndtr/goleveldb/leveldb/opt" 17 "github.com/syndtr/goleveldb/leveldb/util" 18 ) 19 20 type IdHash struct { 21 Id common.Hash `json:"id"` 22 Hash common.Hash `json:"hash"` 23 } 24 25 type LDBDatabase struct { 26 fn string // filename for reporting 27 db *leveldb.DB // LevelDB instance 28 29 quitLock sync.Mutex // Mutex protecting the quit channel access 30 quitChan chan chan error // Quit channel to stop the metrics collection before closing the database 31 } 32 33 // NewLDBDatabase returns a LevelDB wrapped object. 34 func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error) { 35 36 // Ensure we have some minimal caching and file guarantees 37 if cache < 16 { 38 cache = 16 39 } 40 if handles < 16 { 41 handles = 16 42 } 43 44 // Open the db and recover any potential corruptions 45 ldb, err := leveldb.OpenFile(file, &opt.Options{ 46 OpenFilesCacheCapacity: handles, 47 BlockCacheCapacity: cache / 2 * opt.MiB, 48 WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally 49 Filter: filter.NewBloomFilter(10), 50 }) 51 if _, corrupted := err.(*errors.ErrCorrupted); corrupted { 52 ldb, err = leveldb.RecoverFile(file, nil) 53 } 54 // (Re)check for errors and abort if opening of the db failed 55 if err != nil { 56 return nil, err 57 } 58 return &LDBDatabase{ 59 fn: file, 60 db: ldb, 61 }, nil 62 } 63 64 // Path returns the path to the database directory. 65 func (ldb *LDBDatabase) Path() string { 66 return ldb.fn 67 } 68 69 // Put puts the given key / value to the queue 70 func (ldb *LDBDatabase) Put(key []byte, value []byte) error { 71 return ldb.db.Put(key, value, nil) 72 } 73 74 func (ldb *LDBDatabase) Has(key []byte) (bool, error) { 75 return ldb.db.Has(key, nil) 76 } 77 78 // Get returns the given key if it's present. 79 func (ldb *LDBDatabase) Get(key []byte) ([]byte, error) { 80 dat, err := ldb.db.Get(key, nil) 81 if err != nil { 82 return nil, err 83 } 84 return dat, nil 85 } 86 87 // Delete deletes the key from the queue and database 88 func (ldb *LDBDatabase) Delete(key []byte) error { 89 return ldb.db.Delete(key, nil) 90 } 91 92 func (ldb *LDBDatabase) NewIterator() iterator.Iterator { 93 return ldb.db.NewIterator(nil, nil) 94 } 95 96 // NewIteratorWithPrefix returns a iterator to iterate over subset of database content with a particular prefix. 97 func (ldb *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator { 98 return ldb.db.NewIterator(util.BytesPrefix(prefix), nil) 99 } 100 101 func (ldb *LDBDatabase) Close() { 102 // Stop the metrics collection to avoid internal database races 103 ldb.quitLock.Lock() 104 defer ldb.quitLock.Unlock() 105 106 if ldb.quitChan != nil { 107 errc := make(chan error) 108 ldb.quitChan <- errc 109 if err := <-errc; err != nil { 110 fmt.Println("Metrics collection failed", err) 111 } 112 ldb.quitChan = nil 113 } 114 err := ldb.db.Close() 115 if err == nil { 116 fmt.Println("Database closed") 117 } else { 118 fmt.Println("Failed to close database", err) 119 } 120 } 121 122 func (ldb *LDBDatabase) LDB() *leveldb.DB { 123 return ldb.db 124 } 125 126 func (ldb *LDBDatabase) InsertHash(hash []byte, id common.Hash) error { 127 return ldb.Put(hash, id.Bytes()) 128 } 129 130 func (ldb *LDBDatabase) GetHashId(hash []byte) (common.Hash, error) { 131 data, err := ldb.Get(hash) 132 if err != nil { 133 return common.Hash{}, err 134 } 135 return common.BytesToHash(data), nil 136 } 137 138 type RequestParm struct { 139 Hash string 140 } 141 142 func (ldb *LDBDatabase) GetTxId(w http.ResponseWriter, r *http.Request) { 143 req := &RequestParm{} 144 err := json.NewDecoder(r.Body).Decode(req) 145 if err != nil { 146 fmt.Println("json decode error") 147 return 148 } 149 150 hash, err := hexutil.Decode(req.Hash) 151 if err != nil { 152 return 153 } 154 155 id, err := ldb.GetHashId(hash) 156 if err != nil { 157 fmt.Println("no hash", req.Hash) 158 } 159 w.Write(id.Bytes()) 160 }