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  }